pcre2 (empty) → 1.0.0
raw patch · 84 files changed
+121978/−0 lines, 84 filesdep +basedep +containersdep +criterionsetup-changed
Dependencies added: base, containers, criterion, hspec, microlens-platform, mtl, pcre-light, pcre2, regex-pcre-builtin, template-haskell, text
Files
- ChangeLog.md +3/−0
- LICENSE +202/−0
- README.md +66/−0
- Setup.hs +2/−0
- bench/Bench.hs +114/−0
- pcre2.cabal +186/−0
- src/c/config.h +380/−0
- src/c/getters.h +60/−0
- src/c/pcre2.h +993/−0
- src/c/pcre2/maint/ucptest.c +828/−0
- src/c/pcre2/maint/utf8.c +347/−0
- src/c/pcre2/src/pcre2_auto_possess.c +1343/−0
- src/c/pcre2/src/pcre2_compile.c +10499/−0
- src/c/pcre2/src/pcre2_config.c +252/−0
- src/c/pcre2/src/pcre2_context.c +488/−0
- src/c/pcre2/src/pcre2_convert.c +1182/−0
- src/c/pcre2/src/pcre2_dfa_match.c +3982/−0
- src/c/pcre2/src/pcre2_dftables.c +303/−0
- src/c/pcre2/src/pcre2_error.c +340/−0
- src/c/pcre2/src/pcre2_extuni.c +148/−0
- src/c/pcre2/src/pcre2_find_bracket.c +219/−0
- src/c/pcre2/src/pcre2_fuzzsupport.c +365/−0
- src/c/pcre2/src/pcre2_internal.h +2004/−0
- src/c/pcre2/src/pcre2_intmodedep.h +923/−0
- src/c/pcre2/src/pcre2_jit_compile.c +14252/−0
- src/c/pcre2/src/pcre2_jit_match.c +186/−0
- src/c/pcre2/src/pcre2_jit_misc.c +232/−0
- src/c/pcre2/src/pcre2_jit_neon_inc.h +343/−0
- src/c/pcre2/src/pcre2_jit_simd_inc.h +1123/−0
- src/c/pcre2/src/pcre2_jit_test.c +2501/−0
- src/c/pcre2/src/pcre2_maketables.c +163/−0
- src/c/pcre2/src/pcre2_match.c +7311/−0
- src/c/pcre2/src/pcre2_match_data.c +166/−0
- src/c/pcre2/src/pcre2_newline.c +243/−0
- src/c/pcre2/src/pcre2_ord2utf.c +120/−0
- src/c/pcre2/src/pcre2_pattern_info.c +432/−0
- src/c/pcre2/src/pcre2_printint.c +836/−0
- src/c/pcre2/src/pcre2_script_run.c +441/−0
- src/c/pcre2/src/pcre2_serialize.c +286/−0
- src/c/pcre2/src/pcre2_string_utils.c +237/−0
- src/c/pcre2/src/pcre2_study.c +1825/−0
- src/c/pcre2/src/pcre2_substitute.c +987/−0
- src/c/pcre2/src/pcre2_substring.c +547/−0
- src/c/pcre2/src/pcre2_tables.c +854/−0
- src/c/pcre2/src/pcre2_ucd.c +4538/−0
- src/c/pcre2/src/pcre2_ucp.h +299/−0
- src/c/pcre2/src/pcre2_valid_utf.c +398/−0
- src/c/pcre2/src/pcre2_xclass.c +271/−0
- src/c/pcre2/src/pcre2demo.c +494/−0
- src/c/pcre2/src/pcre2grep.c +4553/−0
- src/c/pcre2/src/pcre2posix.c +423/−0
- src/c/pcre2/src/pcre2posix.h +170/−0
- src/c/pcre2/src/pcre2test.c +9220/−0
- src/c/pcre2/src/sljit/sljitConfig.h +172/−0
- src/c/pcre2/src/sljit/sljitConfigInternal.h +800/−0
- src/c/pcre2/src/sljit/sljitExecAllocator.c +385/−0
- src/c/pcre2/src/sljit/sljitLir.c +2702/−0
- src/c/pcre2/src/sljit/sljitLir.h +1544/−0
- src/c/pcre2/src/sljit/sljitNativeARM_32.c +2824/−0
- src/c/pcre2/src/sljit/sljitNativeARM_64.c +2048/−0
- src/c/pcre2/src/sljit/sljitNativeARM_T2_32.c +2383/−0
- src/c/pcre2/src/sljit/sljitNativeMIPS_32.c +671/−0
- src/c/pcre2/src/sljit/sljitNativeMIPS_64.c +672/−0
- src/c/pcre2/src/sljit/sljitNativeMIPS_common.c +2305/−0
- src/c/pcre2/src/sljit/sljitNativePPC_32.c +275/−0
- src/c/pcre2/src/sljit/sljitNativePPC_64.c +495/−0
- src/c/pcre2/src/sljit/sljitNativePPC_common.c +2408/−0
- src/c/pcre2/src/sljit/sljitNativeSPARC_32.c +283/−0
- src/c/pcre2/src/sljit/sljitNativeSPARC_common.c +1554/−0
- src/c/pcre2/src/sljit/sljitNativeTILEGX-encoder.c +10159/−0
- src/c/pcre2/src/sljit/sljitNativeTILEGX_64.c +2565/−0
- src/c/pcre2/src/sljit/sljitNativeX86_32.c +928/−0
- src/c/pcre2/src/sljit/sljitNativeX86_64.c +918/−0
- src/c/pcre2/src/sljit/sljitNativeX86_common.c +3142/−0
- src/c/pcre2/src/sljit/sljitProtExecAllocator.c +474/−0
- src/c/pcre2/src/sljit/sljitUtils.c +337/−0
- src/c/pcre2/src/sljit/sljitWXExecAllocator.c +225/−0
- src/c/pcre2_chartables.c +204/−0
- src/hs/Text/Regex/Pcre2.hs +354/−0
- src/hs/Text/Regex/Pcre2/Foreign.hs +639/−0
- src/hs/Text/Regex/Pcre2/Foreign/TH.hs +37/−0
- src/hs/Text/Regex/Pcre2/Internal.hs +1410/−0
- src/hs/Text/Regex/Pcre2/TH.hs +165/−0
- test/Spec.hs +220/−0
+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for pcre2++## Unreleased changes
+ LICENSE view
@@ -0,0 +1,202 @@++ Apache License+ Version 2.0, January 2004+ http://www.apache.org/licenses/++ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION++ 1. Definitions.++ "License" shall mean the terms and conditions for use, reproduction,+ and distribution as defined by Sections 1 through 9 of this document.++ "Licensor" shall mean the copyright owner or entity authorized by+ the copyright owner that is granting the License.++ "Legal Entity" shall mean the union of the acting entity and all+ other entities that control, are controlled by, or are under common+ control with that entity. For the purposes of this definition,+ "control" means (i) the power, direct or indirect, to cause the+ direction or management of such entity, whether by contract or+ otherwise, or (ii) ownership of fifty percent (50%) or more of the+ outstanding shares, or (iii) beneficial ownership of such entity.++ "You" (or "Your") shall mean an individual or Legal Entity+ exercising permissions granted by this License.++ "Source" form shall mean the preferred form for making modifications,+ including but not limited to software source code, documentation+ source, and configuration files.++ "Object" form shall mean any form resulting from mechanical+ transformation or translation of a Source form, including but+ not limited to compiled object code, generated documentation,+ and conversions to other media types.++ "Work" shall mean the work of authorship, whether in Source or+ Object form, made available under the License, as indicated by a+ copyright notice that is included in or attached to the work+ (an example is provided in the Appendix below).++ "Derivative Works" shall mean any work, whether in Source or Object+ form, that is based on (or derived from) the Work and for which the+ editorial revisions, annotations, elaborations, or other modifications+ represent, as a whole, an original work of authorship. For the purposes+ of this License, Derivative Works shall not include works that remain+ separable from, or merely link (or bind by name) to the interfaces of,+ the Work and Derivative Works thereof.++ "Contribution" shall mean any work of authorship, including+ the original version of the Work and any modifications or additions+ to that Work or Derivative Works thereof, that is intentionally+ submitted to Licensor for inclusion in the Work by the copyright owner+ or by an individual or Legal Entity authorized to submit on behalf of+ the copyright owner. For the purposes of this definition, "submitted"+ means any form of electronic, verbal, or written communication sent+ to the Licensor or its representatives, including but not limited to+ communication on electronic mailing lists, source code control systems,+ and issue tracking systems that are managed by, or on behalf of, the+ Licensor for the purpose of discussing and improving the Work, but+ excluding communication that is conspicuously marked or otherwise+ designated in writing by the copyright owner as "Not a Contribution."++ "Contributor" shall mean Licensor and any individual or Legal Entity+ on behalf of whom a Contribution has been received by Licensor and+ subsequently incorporated within the Work.++ 2. Grant of Copyright License. Subject to the terms and conditions of+ this License, each Contributor hereby grants to You a perpetual,+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable+ copyright license to reproduce, prepare Derivative Works of,+ publicly display, publicly perform, sublicense, and distribute the+ Work and such Derivative Works in Source or Object form.++ 3. Grant of Patent License. Subject to the terms and conditions of+ this License, each Contributor hereby grants to You a perpetual,+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable+ (except as stated in this section) patent license to make, have made,+ use, offer to sell, sell, import, and otherwise transfer the Work,+ where such license applies only to those patent claims licensable+ by such Contributor that are necessarily infringed by their+ Contribution(s) alone or by combination of their Contribution(s)+ with the Work to which such Contribution(s) was submitted. If You+ institute patent litigation against any entity (including a+ cross-claim or counterclaim in a lawsuit) alleging that the Work+ or a Contribution incorporated within the Work constitutes direct+ or contributory patent infringement, then any patent licenses+ granted to You under this License for that Work shall terminate+ as of the date such litigation is filed.++ 4. Redistribution. You may reproduce and distribute copies of the+ Work or Derivative Works thereof in any medium, with or without+ modifications, and in Source or Object form, provided that You+ meet the following conditions:++ (a) You must give any other recipients of the Work or+ Derivative Works a copy of this License; and++ (b) You must cause any modified files to carry prominent notices+ stating that You changed the files; and++ (c) You must retain, in the Source form of any Derivative Works+ that You distribute, all copyright, patent, trademark, and+ attribution notices from the Source form of the Work,+ excluding those notices that do not pertain to any part of+ the Derivative Works; and++ (d) If the Work includes a "NOTICE" text file as part of its+ distribution, then any Derivative Works that You distribute must+ include a readable copy of the attribution notices contained+ within such NOTICE file, excluding those notices that do not+ pertain to any part of the Derivative Works, in at least one+ of the following places: within a NOTICE text file distributed+ as part of the Derivative Works; within the Source form or+ documentation, if provided along with the Derivative Works; or,+ within a display generated by the Derivative Works, if and+ wherever such third-party notices normally appear. The contents+ of the NOTICE file are for informational purposes only and+ do not modify the License. You may add Your own attribution+ notices within Derivative Works that You distribute, alongside+ or as an addendum to the NOTICE text from the Work, provided+ that such additional attribution notices cannot be construed+ as modifying the License.++ You may add Your own copyright statement to Your modifications and+ may provide additional or different license terms and conditions+ for use, reproduction, or distribution of Your modifications, or+ for any such Derivative Works as a whole, provided Your use,+ reproduction, and distribution of the Work otherwise complies with+ the conditions stated in this License.++ 5. Submission of Contributions. Unless You explicitly state otherwise,+ any Contribution intentionally submitted for inclusion in the Work+ by You to the Licensor shall be under the terms and conditions of+ this License, without any additional terms or conditions.+ Notwithstanding the above, nothing herein shall supersede or modify+ the terms of any separate license agreement you may have executed+ with Licensor regarding such Contributions.++ 6. Trademarks. This License does not grant permission to use the trade+ names, trademarks, service marks, or product names of the Licensor,+ except as required for reasonable and customary use in describing the+ origin of the Work and reproducing the content of the NOTICE file.++ 7. Disclaimer of Warranty. Unless required by applicable law or+ agreed to in writing, Licensor provides the Work (and each+ Contributor provides its Contributions) on an "AS IS" BASIS,+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or+ implied, including, without limitation, any warranties or conditions+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A+ PARTICULAR PURPOSE. You are solely responsible for determining the+ appropriateness of using or redistributing the Work and assume any+ risks associated with Your exercise of permissions under this License.++ 8. Limitation of Liability. In no event and under no legal theory,+ whether in tort (including negligence), contract, or otherwise,+ unless required by applicable law (such as deliberate and grossly+ negligent acts) or agreed to in writing, shall any Contributor be+ liable to You for damages, including any direct, indirect, special,+ incidental, or consequential damages of any character arising as a+ result of this License or out of the use or inability to use the+ Work (including but not limited to damages for loss of goodwill,+ work stoppage, computer failure or malfunction, or any and all+ other commercial damages or losses), even if such Contributor+ has been advised of the possibility of such damages.++ 9. Accepting Warranty or Additional Liability. While redistributing+ the Work or Derivative Works thereof, You may choose to offer,+ and charge a fee for, acceptance of support, warranty, indemnity,+ or other liability obligations and/or rights consistent with this+ License. However, in accepting such obligations, You may act only+ on Your own behalf and on Your sole responsibility, not on behalf+ of any other Contributor, and only if You agree to indemnify,+ defend, and hold each Contributor harmless for any liability+ incurred by, or claims asserted against, such Contributor by reason+ of your accepting any such warranty or additional liability.++ END OF TERMS AND CONDITIONS++ APPENDIX: How to apply the Apache License to your work.++ To apply the Apache License to your work, attach the following+ boilerplate notice, with the fields enclosed by brackets "[]"+ replaced with your own identifying information. (Don't include+ the brackets!) The text should be enclosed in the appropriate+ comment syntax for the file format. We also recommend that a+ file or class name and description of purpose be included on the+ same "printed page" as the copyright notice for easier+ identification within third-party archives.++ Copyright [yyyy] [name of copyright owner]++ Licensed under the Apache License, Version 2.0 (the "License");+ you may not use this file except in compliance with the License.+ You may obtain a copy of the License at++ http://www.apache.org/licenses/LICENSE-2.0++ Unless required by applicable law or agreed to in writing, software+ distributed under the License is distributed on an "AS IS" BASIS,+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ See the License for the specific language governing permissions and+ limitations under the License.
+ README.md view
@@ -0,0 +1,66 @@+# pcre2++Regular expressions for Haskell.++## Teasers+```haskell+embeddedLicensePlate :: Text -> Maybe Text+embeddedLicensePlate = match "[A-Z]{3}[0-9]{3,4}"+```+```haskell+case "The quick brown fox" of+ [regex|brown\s+(?<animal>\S+)|] -> Text.putStrLn animal+ _ -> error "nothing brown"+```+```haskell+let kv'd = lined . packed . [_regex|^\s*(.*?)\s*[=:]\s*(.*)|]++forMOf kv'd file $ execStateT $ do+ k <- gets $ capture @1+ v <- gets $ capture @2+ liftIO $ Text.putStrLn $ "found " <> k <> " set to " <> v++ case myMap ^. at k of+ Just v' | v /= v' -> do+ liftIO $ Text.putStrLn $ "setting " <> k <> " to " <> v'+ _capture @2 .= v'+ _ -> liftIO $ Text.putStrLn "no change"+```++## Features+* Low-surface API covering most use cases.+* Quiet functions with simple types—for the most part it's +`Text` _(pattern)_ `-> Text` _(subject)_ `-> result`.+* Use partial application to create performant, compile-once-match-many code.+* Low cognitive overhead—there's just one custom datatype for both compile+ and match options, the `Option` monoid.+* `Text` everywhere for interop with both C and the broader Haskell ecosystem.+* Match failures expressed via `Alternative` or pattern match failures.+* Opt-in Template Haskell facilities for compile-time verification of patterns,+ indexing captures, and memoizing inline regexes.+* Opt-in `lens` support.+* No failure monads to express compile errors, preferring pure functions and+ throwing imprecise exceptions with pretty `Show` instances. Write simple+ code and debug it. Or, don't, and use the Template Haskell features instead.+ Both are first-class.+* Vast presentation of PCRE2 functionality. We can even register Haskell+ callbacks to run during matching!+* No dependencies that aren't distributed with GHC.+* Bundled, statically-linked UTF-16 build of ~~up-to-date~~ PCRE2 (version+ 10.35), with a complete, exposed Haskell binding.++## TODO+* Global matching. (We already have global substitution.)+* Many performance optimizations. Currently we are 2–3× slower+ than other libraries doing everything (a few μs).+* Make use of DFA and JIT compilation.+* Establish automated builds.+* Improve PCRE2 C compile time.+* PCRE2 10.36 is out already.++## License+[Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0.html). +PCRE2 is distributed under the [3-clause BSD](https://www.pcre.org/licence.txt) license.++## Author+©2020 Shlomo Shuck
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ bench/Bench.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}++module Main where++import Criterion.Main+import Data.List.NonEmpty (NonEmpty(..))+import qualified Data.Text as Text+import Lens.Micro.Platform+import System.IO.Unsafe (unsafePerformIO)+import qualified Text.Regex.PCRE+import qualified Text.Regex.PCRE.Light.Char8+import qualified Text.Regex.PCRE.String+import qualified Text.Regex.PCRE.Text+import Text.Regex.Pcre2++main :: IO ()+main = defaultMain [+ bgroup "creating single-use regexes" [+ bench "pcre2" $ flip nf strings $ \(patt, subj) ->+ let Just (_ :| [bar]) = capturesA (Text.pack patt) (Text.pack subj)+ in Text.unpack bar,++ bench "regex-pcre-builtin" $ flip nf strings $ \(patt, subj) ->+ let r = Text.Regex.PCRE.makeRegex patt :: Text.Regex.PCRE.Regex+ results :: (String, String, String)+ results@(_, result, _) = Text.Regex.PCRE.match r subj+ in result,++ bench "pcre-light" $ flip nf strings $ \(patt, subj) ->+ let r = Text.Regex.PCRE.Light.Char8.compile patt []+ Just [_, bar] = Text.Regex.PCRE.Light.Char8.match r subj []+ in bar],+ + bgroup "strings" [+ let r = capturesA $ Text.pack stringPattern+ in bench "pcre2" $ flip nf stringSubject $ \subj ->+ let Just (_ :| [bar]) = r $ Text.pack subj in Text.unpack bar,++ let r = mkRegexBaseR stringPattern+ in bench "regex-pcre-builtin" $ nfIO $ do+ Right (Just (_, _, _, [bar])) <-+ Text.Regex.PCRE.String.regexec r stringSubject+ return bar,++ let r = Text.Regex.PCRE.Light.Char8.compile stringPattern []+ in bench "pcre-light" $ flip nf stringSubject $ \subj ->+ let Just [_, bar] = Text.Regex.PCRE.Light.Char8.match r subj []+ in bar],++ bgroup "texts" [+ bgroupTexts "short" strings,++ bgroupTexts "long" (+ "foo (ba*r) baz",+ "foo b" ++ replicate 1000 'a' ++ "r baz")],++ bgroup "Template Haskell" [+ bench "pattern with named capture" $ flip nf textSubject $ \subj ->+ let [regex|foo (?<bar>bar) baz|] = subj in bar,++ bench "expression with capture" $ flip nf textSubject $ \subj ->+ let Just cs = [regex|foo (?<bar>bar) baz|] subj+ in capture @"bar" cs],++ bgroup "substitutions" [+ bench "PCRE2-native" $ flip nf textSubject $+ sub (Text.pack "(?<=foo )bar(?= baz)") (Text.pack "quux"),++ let quux = Text.pack "quux"+ in bench "lens-powered" $ flip nf textSubject $+ set ([_regex|foo (bar) baz|] . _capture @1) quux]]++stringPattern = "foo (bar) baz"+stringSubject = "foo bar baz"+strings = (stringPattern, stringSubject)++textPattern = Text.pack "foo (bar) baz"+textSubject = Text.pack "foo bar baz"++mkRegexBaseR :: String -> Text.Regex.PCRE.Regex+mkRegexBaseR patt = unsafePerformIO $ do+ Right r <- Text.Regex.PCRE.String.compile 0 0 patt+ return r++bgroupTexts :: String -> (String, String) -> Benchmark+bgroupTexts label (patt, subj) = bgroup label [+ bench "pcre2" $ flip nf textSubject $ \subj ->+ let Just (_ :| [bar]) = pcre2R subj in bar,++ bench "regex-pcre-builtin" $ nfIO $ do+ Text.Regex.PCRE.Text.regexec regexBaseR textSubject >>= \case+ Right (Just (_, _, _, [bar])) -> return bar+ x -> do+ print x+ error "BUG!",++ bench "pcre-light" $ flip nf textSubject $ \subj ->+ let Just [_, bar] = Text.Regex.PCRE.Light.Char8.match+ pcreLightR+ (Text.unpack subj)+ []+ in bar]++ where+ textPattern = Text.pack patt+ textSubject = Text.pack subj+ pcre2R = capturesA textPattern+ regexBaseR = mkRegexBaseR patt+ pcreLightR = Text.Regex.PCRE.Light.Char8.compile patt []
+ pcre2.cabal view
@@ -0,0 +1,186 @@+cabal-version: 1.12+name: pcre2+version: 1.0.0+license: Apache-2.0+license-file: LICENSE+copyright: 2020 Shlomo Shuck+maintainer: stevenjshuck@gmail.com+author: Shlomo Shuck+homepage: https://github.com/sjshuck/hs-pcre2#readme+bug-reports: https://github.com/sjshuck/hs-pcre2/issues+synopsis: Regular expressions via the PCRE2 C library (included)+description:+ Please see the README on GitHub at <https://github.com/sjshuck/hs-pcre2>++category: Text+build-type: Simple+extra-source-files:+ README.md+ ChangeLog.md+ src/c/config.h+ src/c/getters.h+ src/c/pcre2.h+ src/c/pcre2/src/pcre2_internal.h+ src/c/pcre2/src/pcre2_intmodedep.h+ src/c/pcre2/src/pcre2_jit_neon_inc.h+ src/c/pcre2/src/pcre2_jit_simd_inc.h+ src/c/pcre2/src/pcre2_ucp.h+ src/c/pcre2/src/pcre2posix.h+ src/c/pcre2/src/sljit/sljitConfig.h+ src/c/pcre2/src/sljit/sljitConfigInternal.h+ src/c/pcre2/src/sljit/sljitLir.h+ src/c/pcre2/maint/ucptest.c+ src/c/pcre2/maint/utf8.c+ src/c/pcre2/src/pcre2_auto_possess.c+ src/c/pcre2/src/pcre2_compile.c+ src/c/pcre2/src/pcre2_config.c+ src/c/pcre2/src/pcre2_context.c+ src/c/pcre2/src/pcre2_convert.c+ src/c/pcre2/src/pcre2_dfa_match.c+ src/c/pcre2/src/pcre2_dftables.c+ src/c/pcre2/src/pcre2_error.c+ src/c/pcre2/src/pcre2_extuni.c+ src/c/pcre2/src/pcre2_find_bracket.c+ src/c/pcre2/src/pcre2_fuzzsupport.c+ src/c/pcre2/src/pcre2_jit_compile.c+ src/c/pcre2/src/pcre2_jit_match.c+ src/c/pcre2/src/pcre2_jit_misc.c+ src/c/pcre2/src/pcre2_jit_test.c+ src/c/pcre2/src/pcre2_maketables.c+ src/c/pcre2/src/pcre2_match.c+ src/c/pcre2/src/pcre2_match_data.c+ src/c/pcre2/src/pcre2_newline.c+ src/c/pcre2/src/pcre2_ord2utf.c+ src/c/pcre2/src/pcre2_pattern_info.c+ src/c/pcre2/src/pcre2_printint.c+ src/c/pcre2/src/pcre2_script_run.c+ src/c/pcre2/src/pcre2_serialize.c+ src/c/pcre2/src/pcre2_string_utils.c+ src/c/pcre2/src/pcre2_study.c+ src/c/pcre2/src/pcre2_substitute.c+ src/c/pcre2/src/pcre2_substring.c+ src/c/pcre2/src/pcre2_tables.c+ src/c/pcre2/src/pcre2_ucd.c+ src/c/pcre2/src/pcre2_valid_utf.c+ src/c/pcre2/src/pcre2_xclass.c+ src/c/pcre2/src/pcre2demo.c+ src/c/pcre2/src/pcre2grep.c+ src/c/pcre2/src/pcre2posix.c+ src/c/pcre2/src/pcre2test.c+ src/c/pcre2/src/sljit/sljitExecAllocator.c+ src/c/pcre2/src/sljit/sljitLir.c+ src/c/pcre2/src/sljit/sljitNativeARM_32.c+ src/c/pcre2/src/sljit/sljitNativeARM_64.c+ src/c/pcre2/src/sljit/sljitNativeARM_T2_32.c+ src/c/pcre2/src/sljit/sljitNativeMIPS_32.c+ src/c/pcre2/src/sljit/sljitNativeMIPS_64.c+ src/c/pcre2/src/sljit/sljitNativeMIPS_common.c+ src/c/pcre2/src/sljit/sljitNativePPC_32.c+ src/c/pcre2/src/sljit/sljitNativePPC_64.c+ src/c/pcre2/src/sljit/sljitNativePPC_common.c+ src/c/pcre2/src/sljit/sljitNativeSPARC_32.c+ src/c/pcre2/src/sljit/sljitNativeSPARC_common.c+ src/c/pcre2/src/sljit/sljitNativeTILEGX-encoder.c+ src/c/pcre2/src/sljit/sljitNativeTILEGX_64.c+ src/c/pcre2/src/sljit/sljitNativeX86_32.c+ src/c/pcre2/src/sljit/sljitNativeX86_64.c+ src/c/pcre2/src/sljit/sljitNativeX86_common.c+ src/c/pcre2/src/sljit/sljitProtExecAllocator.c+ src/c/pcre2/src/sljit/sljitUtils.c+ src/c/pcre2/src/sljit/sljitWXExecAllocator.c+ src/c/pcre2_chartables.c++source-repository head+ type: git+ location: https://github.com/sjshuck/hs-pcre2++library+ exposed-modules:+ Text.Regex.Pcre2+ Text.Regex.Pcre2.Foreign++ cc-options: -DHAVE_CONFIG_H -DPCRE2_CODE_UNIT_WIDTH=16+ c-sources:+ src/c/pcre2/src/pcre2_auto_possess.c+ src/c/pcre2_chartables.c+ src/c/pcre2/src/pcre2_compile.c+ src/c/pcre2/src/pcre2_config.c+ src/c/pcre2/src/pcre2_context.c+ src/c/pcre2/src/pcre2_convert.c+ src/c/pcre2/src/pcre2_dfa_match.c+ src/c/pcre2/src/pcre2_error.c+ src/c/pcre2/src/pcre2_extuni.c+ src/c/pcre2/src/pcre2_find_bracket.c+ src/c/pcre2/src/pcre2_jit_compile.c+ src/c/pcre2/src/pcre2_maketables.c+ src/c/pcre2/src/pcre2_match.c+ src/c/pcre2/src/pcre2_match_data.c+ src/c/pcre2/src/pcre2_newline.c+ src/c/pcre2/src/pcre2_ord2utf.c+ src/c/pcre2/src/pcre2_pattern_info.c+ src/c/pcre2/src/pcre2_script_run.c+ src/c/pcre2/src/pcre2_serialize.c+ src/c/pcre2/src/pcre2_string_utils.c+ src/c/pcre2/src/pcre2_study.c+ src/c/pcre2/src/pcre2_substitute.c+ src/c/pcre2/src/pcre2_substring.c+ src/c/pcre2/src/pcre2_tables.c+ src/c/pcre2/src/pcre2_ucd.c+ src/c/pcre2/src/pcre2_valid_utf.c+ src/c/pcre2/src/pcre2_xclass.c++ hs-source-dirs: src/hs+ other-modules:+ Text.Regex.Pcre2.Foreign.TH+ Text.Regex.Pcre2.Internal+ Text.Regex.Pcre2.TH+ Paths_pcre2++ default-language: Haskell2010+ include-dirs: src/c src/c/pcre2/src+ ghc-options:+ -optc=-DPCRE2_CODE_UNIT_WIDTH=16 -optc=-Wno-discarded-qualifiers+ -optc=-Wno-incompatible-pointer-types++ build-depends:+ base >=4.7 && <5,+ containers >=0.6.2.1 && <0.7,+ mtl >=2.2.2 && <2.3,+ template-haskell >=2.15.0.0 && <2.16,+ text >=1.2.4.0 && <1.3++test-suite pcre2-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs: test+ other-modules: Paths_pcre2+ default-language: Haskell2010+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base >=4.7 && <5,+ containers >=0.6.2.1 && <0.7,+ hspec >=2.7.4 && <2.8,+ microlens-platform >=0.4.2 && <0.5,+ mtl >=2.2.2 && <2.3,+ pcre2 -any,+ template-haskell >=2.15.0.0 && <2.16,+ text >=1.2.4.0 && <1.3++benchmark pcre2-benchmarks+ type: exitcode-stdio-1.0+ main-is: Bench.hs+ hs-source-dirs: bench+ other-modules: Paths_pcre2+ default-language: Haskell2010+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base >=4.7 && <5,+ containers >=0.6.2.1 && <0.7,+ criterion >=1.5.7.0 && <1.6,+ microlens-platform >=0.4.2 && <0.5,+ mtl >=2.2.2 && <2.3,+ pcre-light >=0.4.1.0 && <0.5,+ pcre2 -any,+ regex-pcre-builtin >=0.95.1.3.8.43 && <0.96,+ template-haskell >=2.15.0.0 && <2.16,+ text >=1.2.4.0 && <1.3
+ src/c/config.h view
@@ -0,0 +1,380 @@+// Copied and edited per the PCRE2 source's NON-AUTOTOOLS-BUILD instructions.++/* PCRE2 is written in Standard C, but there are a few non-standard things it+can cope with, allowing it to run on SunOS4 and other "close to standard"+systems.++In environments that support the GNU autotools, config.h.in is converted into+config.h by the "configure" script. In environments that use CMake,+config-cmake.in is converted into config.h. If you are going to build PCRE2 "by+hand" without using "configure" or CMake, you should copy the distributed+config.h.generic to config.h, and edit the macro definitions to be the way you+need them. You must then add -DHAVE_CONFIG_H to all of your compile commands,+so that config.h is included at the start of every source.++Alternatively, you can avoid editing by using -D on the compiler command line+to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H,+but if you do, default values will be taken from config.h for non-boolean+macros that are not defined on the command line.++Boolean macros such as HAVE_STDLIB_H and SUPPORT_PCRE2_8 should either be+defined (conventionally to 1) for TRUE, and not defined at all for FALSE. All+such macros are listed as a commented #undef in config.h.generic. Macros such+as MATCH_LIMIT, whose actual value is relevant, have defaults defined, but are+surrounded by #ifndef/#endif lines so that the value can be overridden by -D.++PCRE2 uses memmove() if HAVE_MEMMOVE is defined; otherwise it uses bcopy() if+HAVE_BCOPY is defined. If your system has neither bcopy() nor memmove(), make+sure both macros are undefined; an emulation function will then be used. */++/* By default, the \R escape sequence matches any Unicode line ending+ character or sequence of characters. If BSR_ANYCRLF is defined (to any+ value), this is changed so that backslash-R matches only CR, LF, or CRLF.+ The build-time default can be overridden by the user of PCRE2 at runtime.+ */+/* #undef BSR_ANYCRLF */++/* Define to any value to disable the use of the z and t modifiers in+ formatting settings such as %zu or %td (this is rarely needed). */+/* #undef DISABLE_PERCENT_ZT */++/* If you are compiling for a system that uses EBCDIC instead of ASCII+ character codes, define this macro to any value. When EBCDIC is set, PCRE2+ assumes that all input strings are in EBCDIC. If you do not define this+ macro, PCRE2 will assume input strings are ASCII or UTF-8/16/32 Unicode. It+ is not possible to build a version of PCRE2 that supports both EBCDIC and+ UTF-8/16/32. */+/* #undef EBCDIC */++/* In an EBCDIC environment, define this macro to any value to arrange for the+ NL character to be 0x25 instead of the default 0x15. NL plays the role that+ LF does in an ASCII/Unicode environment. */+/* #undef EBCDIC_NL25 */++/* Define this if your compiler supports __attribute__((uninitialized)) */+/* #undef HAVE_ATTRIBUTE_UNINITIALIZED */++/* Define to 1 if you have the `bcopy' function. */+/* #undef HAVE_BCOPY */++/* Define to 1 if you have the <bzlib.h> header file. */+/* #undef HAVE_BZLIB_H */++/* Define to 1 if you have the <dirent.h> header file. */+/* #undef HAVE_DIRENT_H */++/* Define to 1 if you have the <dlfcn.h> header file. */+/* #undef HAVE_DLFCN_H */++/* Define to 1 if you have the <editline/readline.h> header file. */+/* #undef HAVE_EDITLINE_READLINE_H */++/* Define to 1 if you have the <edit/readline/readline.h> header file. */+/* #undef HAVE_EDIT_READLINE_READLINE_H */++/* Define to 1 if you have the <inttypes.h> header file. */+#define HAVE_INTTYPES_H 1++/* Define to 1 if you have the <limits.h> header file. */+#define HAVE_LIMITS_H 1++/* Define to 1 if you have the `memfd_create' function. */+/* #undef HAVE_MEMFD_CREATE */++/* Define to 1 if you have the `memmove' function. */+#define HAVE_MEMMOVE 1++/* Define to 1 if you have the <memory.h> header file. */+/* #undef HAVE_MEMORY_H */++/* Define to 1 if you have the `mkostemp' function. */+/* #undef HAVE_MKOSTEMP */++/* Define if you have POSIX threads libraries and header files. */+/* #undef HAVE_PTHREAD */++/* Have PTHREAD_PRIO_INHERIT. */+/* #undef HAVE_PTHREAD_PRIO_INHERIT */++/* Define to 1 if you have the <readline/history.h> header file. */+/* #undef HAVE_READLINE_HISTORY_H */++/* Define to 1 if you have the <readline/readline.h> header file. */+/* #undef HAVE_READLINE_READLINE_H */++/* Define to 1 if you have the `secure_getenv' function. */+/* #undef HAVE_SECURE_GETENV */++/* Define to 1 if you have the <stdint.h> header file. */+#define HAVE_STDINT_H 1++/* Define to 1 if you have the <stdlib.h> header file. */+#define HAVE_STDLIB_H 1++/* Define to 1 if you have the `strerror' function. */+#define HAVE_STRERROR 1++/* Define to 1 if you have the <strings.h> header file. */+/* #undef HAVE_STRINGS_H */++/* Define to 1 if you have the <string.h> header file. */+#define HAVE_STRING_H 1++/* Define to 1 if you have the <sys/stat.h> header file. */+/* #undef HAVE_SYS_STAT_H */++/* Define to 1 if you have the <sys/types.h> header file. */+/* #undef HAVE_SYS_TYPES_H */++/* Define to 1 if you have the <sys/wait.h> header file. */+/* #undef HAVE_SYS_WAIT_H */++/* Define to 1 if you have the <unistd.h> header file. */+/* #undef HAVE_UNISTD_H */++/* Define to 1 if the compiler supports simple visibility declarations. */+/* #undef HAVE_VISIBILITY */++/* Define to 1 if you have the <windows.h> header file. */+/* #undef HAVE_WINDOWS_H */++/* Define to 1 if you have the <zlib.h> header file. */+/* #undef HAVE_ZLIB_H */++/* This limits the amount of memory that may be used while matching a pattern.+ It applies to both pcre2_match() and pcre2_dfa_match(). It does not apply+ to JIT matching. The value is in kibibytes (units of 1024 bytes). */+#ifndef HEAP_LIMIT+#define HEAP_LIMIT 20000000+#endif++/* The value of LINK_SIZE determines the number of bytes used to store links+ as offsets within the compiled regex. The default is 2, which allows for+ compiled patterns up to 65535 code units long. This covers the vast+ majority of cases. However, PCRE2 can also be compiled to use 3 or 4 bytes+ instead. This allows for longer patterns in extreme cases. */+#ifndef LINK_SIZE+#define LINK_SIZE 2+#endif++/* Define to the sub-directory where libtool stores uninstalled libraries. */+/* This is ignored unless you are using libtool. */+#ifndef LT_OBJDIR+#define LT_OBJDIR ".libs/"+#endif++/* The value of MATCH_LIMIT determines the default number of times the+ pcre2_match() function can record a backtrack position during a single+ matching attempt. The value is also used to limit a loop counter in+ pcre2_dfa_match(). There is a runtime interface for setting a different+ limit. The limit exists in order to catch runaway regular expressions that+ take for ever to determine that they do not match. The default is set very+ large so that it does not accidentally catch legitimate cases. */+#ifndef MATCH_LIMIT+#define MATCH_LIMIT 10000000+#endif++/* The above limit applies to all backtracks, whether or not they are nested.+ In some environments it is desirable to limit the nesting of backtracking+ (that is, the depth of tree that is searched) more strictly, in order to+ restrict the maximum amount of heap memory that is used. The value of+ MATCH_LIMIT_DEPTH provides this facility. To have any useful effect, it+ must be less than the value of MATCH_LIMIT. The default is to use the same+ value as MATCH_LIMIT. There is a runtime method for setting a different+ limit. In the case of pcre2_dfa_match(), this limit controls the depth of+ the internal nested function calls that are used for pattern recursions,+ lookarounds, and atomic groups. */+#ifndef MATCH_LIMIT_DEPTH+#define MATCH_LIMIT_DEPTH MATCH_LIMIT+#endif++/* This limit is parameterized just in case anybody ever wants to change it.+ Care must be taken if it is increased, because it guards against integer+ overflow caused by enormously large patterns. */+#ifndef MAX_NAME_COUNT+#define MAX_NAME_COUNT 10000+#endif++/* This limit is parameterized just in case anybody ever wants to change it.+ Care must be taken if it is increased, because it guards against integer+ overflow caused by enormously large patterns. */+#ifndef MAX_NAME_SIZE+#define MAX_NAME_SIZE 32+#endif++/* Defining NEVER_BACKSLASH_C locks out the use of \C in all patterns. */+/* #undef NEVER_BACKSLASH_C */++/* The value of NEWLINE_DEFAULT determines the default newline character+ sequence. PCRE2 client programs can override this by selecting other values+ at run time. The valid values are 1 (CR), 2 (LF), 3 (CRLF), 4 (ANY), 5+ (ANYCRLF), and 6 (NUL). */+#ifndef NEWLINE_DEFAULT+#define NEWLINE_DEFAULT 2+#endif++/* Name of package */+#define PACKAGE "pcre2"++/* Define to the address where bug reports for this package should be sent. */+#define PACKAGE_BUGREPORT ""++/* Define to the full name of this package. */+#define PACKAGE_NAME "PCRE2"++/* Define to the full name and version of this package. */+#define PACKAGE_STRING "PCRE2 10.35"++/* Define to the one symbol short name of this package. */+#define PACKAGE_TARNAME "pcre2"++/* Define to the home page for this package. */+#define PACKAGE_URL ""++/* Define to the version of this package. */+#define PACKAGE_VERSION "10.35"++/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested+ parentheses (of any kind) in a pattern. This limits the amount of system+ stack that is used while compiling a pattern. */+#ifndef PARENS_NEST_LIMIT+#define PARENS_NEST_LIMIT 250+#endif++/* The value of PCRE2GREP_BUFSIZE is the starting size of the buffer used by+ pcre2grep to hold parts of the file it is searching. The buffer will be+ expanded up to PCRE2GREP_MAX_BUFSIZE if necessary, for files containing+ very long lines. The actual amount of memory used by pcre2grep is three+ times this number, because it allows for the buffering of "before" and+ "after" lines. */+#ifndef PCRE2GREP_BUFSIZE+#define PCRE2GREP_BUFSIZE 20480+#endif++/* The value of PCRE2GREP_MAX_BUFSIZE specifies the maximum size of the buffer+ used by pcre2grep to hold parts of the file it is searching. The actual+ amount of memory used by pcre2grep is three times this number, because it+ allows for the buffering of "before" and "after" lines. */+#ifndef PCRE2GREP_MAX_BUFSIZE+#define PCRE2GREP_MAX_BUFSIZE 1048576+#endif++/* Define to any value to include debugging code. */+/* #undef PCRE2_DEBUG */++/* If you are compiling for a system other than a Unix-like system or+ Win32, and it needs some magic to be inserted before the definition+ of a function that is exported by the library, define this macro to+ contain the relevant magic. If you do not define this macro, a suitable+ __declspec value is used for Windows systems; in other environments+ "extern" is used for a C compiler and "extern C" for a C++ compiler.+ This macro apears at the start of every exported function that is part+ of the external API. It does not appear on functions that are "external"+ in the C sense, but which are internal to the library. */+/* #undef PCRE2_EXP_DEFN */++/* Define to any value if linking statically (TODO: make nice with Libtool) */+#define PCRE2_STATIC 1++/* Define to necessary symbol if this constant uses a non-standard name on+ your system. */+/* #undef PTHREAD_CREATE_JOINABLE */++/* Define to any non-zero number to enable support for SELinux compatible+ executable memory allocator in JIT. Note that this will have no effect+ unless SUPPORT_JIT is also defined. */+/* #undef SLJIT_PROT_EXECUTABLE_ALLOCATOR */++/* Define to 1 if you have the ANSI C header files. */+#define STDC_HEADERS 1++/* Define to any value to enable support for Just-In-Time compiling. */+#define SUPPORT_JIT 1++/* Define to any value to allow pcre2grep to be linked with libbz2, so that it+ is able to handle .bz2 files. */+/* #undef SUPPORT_LIBBZ2 */++/* Define to any value to allow pcre2test to be linked with libedit. */+/* #undef SUPPORT_LIBEDIT */++/* Define to any value to allow pcre2test to be linked with libreadline. */+/* #undef SUPPORT_LIBREADLINE */++/* Define to any value to allow pcre2grep to be linked with libz, so that it+ is able to handle .gz files. */+/* #undef SUPPORT_LIBZ */++/* Define to any value to enable callout script support in pcre2grep. */+/* #undef SUPPORT_PCRE2GREP_CALLOUT */++/* Define to any value to enable fork support in pcre2grep callout scripts.+ This will have no effect unless SUPPORT_PCRE2GREP_CALLOUT is also defined.+ */+/* #undef SUPPORT_PCRE2GREP_CALLOUT_FORK */++/* Define to any value to enable JIT support in pcre2grep. Note that this will+ have no effect unless SUPPORT_JIT is also defined. */+/* #undef SUPPORT_PCRE2GREP_JIT */++/* Define to any value to enable the 16 bit PCRE2 library. */+#define SUPPORT_PCRE2_16 1++/* Define to any value to enable the 32 bit PCRE2 library. */+/* #undef SUPPORT_PCRE2_32 */++/* Define to any value to enable the 8 bit PCRE2 library. */+/* #undef SUPPORT_PCRE2_8 */++/* Define to any value to enable support for Unicode and UTF encoding. This+ will work even in an EBCDIC environment, but it is incompatible with the+ EBCDIC macro. That is, PCRE2 can support *either* EBCDIC code *or*+ ASCII/Unicode, but not both at once. */+#define SUPPORT_UNICODE 1++/* Define to any value for valgrind support to find invalid memory reads. */+/* #undef SUPPORT_VALGRIND */++/* Enable extensions on AIX 3, Interix. */+#ifndef _ALL_SOURCE+# define _ALL_SOURCE 1+#endif+/* Enable GNU extensions on systems that have them. */+#ifndef _GNU_SOURCE+# define _GNU_SOURCE 1+#endif+/* Enable threading extensions on Solaris. */+#ifndef _POSIX_PTHREAD_SEMANTICS+# define _POSIX_PTHREAD_SEMANTICS 1+#endif+/* Enable extensions on HP NonStop. */+#ifndef _TANDEM_SOURCE+# define _TANDEM_SOURCE 1+#endif+/* Enable general extensions on Solaris. */+#ifndef __EXTENSIONS__+# define __EXTENSIONS__ 1+#endif++/* Version number of package */+#define VERSION "10.35"++/* Define to 1 if on MINIX. */+/* #undef _MINIX */++/* Define to 2 if the system does not provide POSIX.1 features except with+ this defined. */+/* #undef _POSIX_1_SOURCE */++/* Define to 1 if you need to in order for `stat' and other things to work. */+/* #undef _POSIX_SOURCE */++/* Define to empty if `const' does not conform to ANSI C. */+/* #undef const */++/* Define to the type of a signed integer type of width exactly 64 bits if+ such a type exists and the standard includes do not define it. */+/* #undef int64_t */++/* Define to `unsigned int' if <sys/types.h> does not define. */+/* #undef size_t */
+ src/c/getters.h view
@@ -0,0 +1,60 @@+// Functions to get PCRE2 struct fields.++#include <pcre2.h>++#ifndef GETTERS_H+#define GETTERS_H++#ifdef GETTER+#error GETTER already defined+#endif+#define GETTER(src, field, ret) \+ ret pcre2_##src##_##field(pcre2_##src *block) \+ { \+ return block->field; \+ }++/*+ For example, the first of these produces the following code:++ uint32_t pcre2_callout_block_version(pcre2_callout_block *block)+ {+ return block->version;+ }+*/+GETTER(callout_block, version, uint32_t)+GETTER(callout_block, callout_number, uint32_t)+GETTER(callout_block, capture_top, uint32_t)+GETTER(callout_block, capture_last, uint32_t)+GETTER(callout_block, callout_flags, uint32_t)+GETTER(callout_block, offset_vector, PCRE2_SIZE *)+GETTER(callout_block, mark, PCRE2_SPTR)+GETTER(callout_block, subject, PCRE2_SPTR)+GETTER(callout_block, subject_length, PCRE2_SIZE)+GETTER(callout_block, start_match, PCRE2_SIZE)+GETTER(callout_block, current_position, PCRE2_SIZE)+GETTER(callout_block, pattern_position, PCRE2_SIZE)+GETTER(callout_block, next_item_length, PCRE2_SIZE)+GETTER(callout_block, callout_string_offset, PCRE2_SIZE)+GETTER(callout_block, callout_string_length, PCRE2_SIZE)+GETTER(callout_block, callout_string, PCRE2_SPTR)++GETTER(callout_enumerate_block, version, uint32_t)+GETTER(callout_enumerate_block, pattern_position, PCRE2_SIZE)+GETTER(callout_enumerate_block, next_item_length, PCRE2_SIZE)+GETTER(callout_enumerate_block, callout_number, uint32_t)+GETTER(callout_enumerate_block, callout_string_offset, PCRE2_SIZE)+GETTER(callout_enumerate_block, callout_string_length, PCRE2_SIZE)+GETTER(callout_enumerate_block, callout_string, PCRE2_SPTR)++GETTER(substitute_callout_block, version, uint32_t)+GETTER(substitute_callout_block, subscount, uint32_t)+GETTER(substitute_callout_block, input, PCRE2_SPTR)+GETTER(substitute_callout_block, output, PCRE2_SPTR)+GETTER(substitute_callout_block, ovector, PCRE2_SIZE *)+GETTER(substitute_callout_block, oveccount, uint32_t)+GETTER(substitute_callout_block, output_offsets, PCRE2_SIZE *) // array of 2++#undef GETTER++#endif
+ src/c/pcre2.h view
@@ -0,0 +1,993 @@+// Copied per the PCRE2 source's NON-AUTOTOOLS-BUILD instructions.++/*************************************************+* Perl-Compatible Regular Expressions *+*************************************************/++/* This is the public header file for the PCRE library, second API, to be+#included by applications that call PCRE2 functions.++ Copyright (c) 2016-2020 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.+-----------------------------------------------------------------------------+*/++#ifndef PCRE2_H_IDEMPOTENT_GUARD+#define PCRE2_H_IDEMPOTENT_GUARD++/* The current PCRE version information. */++#define PCRE2_MAJOR 10+#define PCRE2_MINOR 35+#define PCRE2_PRERELEASE +#define PCRE2_DATE 2020-05-09++/* When an application links to a PCRE DLL in Windows, the symbols that are+imported have to be identified as such. When building PCRE2, the appropriate+export setting is defined in pcre2_internal.h, which includes this file. So we+don't change existing definitions of PCRE2_EXP_DECL. */++#if defined(_WIN32) && !defined(PCRE2_STATIC)+# ifndef PCRE2_EXP_DECL+# define PCRE2_EXP_DECL extern __declspec(dllimport)+# endif+#endif++/* By default, we use the standard "extern" declarations. */++#ifndef PCRE2_EXP_DECL+# ifdef __cplusplus+# define PCRE2_EXP_DECL extern "C"+# else+# define PCRE2_EXP_DECL extern+# endif+#endif++/* When compiling with the MSVC compiler, it is sometimes necessary to include+a "calling convention" before exported function names. (This is secondhand+information; I know nothing about MSVC myself). For example, something like++ void __cdecl function(....)++might be needed. In order so make this easy, all the exported functions have+PCRE2_CALL_CONVENTION just before their names. It is rarely needed; if not+set, we ensure here that it has no effect. */++#ifndef PCRE2_CALL_CONVENTION+#define PCRE2_CALL_CONVENTION+#endif++/* Have to include limits.h, stdlib.h, and inttypes.h to ensure that size_t and+uint8_t, UCHAR_MAX, etc are defined. Some systems that do have inttypes.h do+not have stdint.h, which is why we use inttypes.h, which according to the C+standard is a superset of stdint.h. If none of these headers are available,+the relevant values must be provided by some other means. */++#include <limits.h>+#include <stdlib.h>+#include <inttypes.h>++/* Allow for C++ users compiling this directly. */++#ifdef __cplusplus+extern "C" {+#endif++/* The following option bits can be passed to pcre2_compile(), pcre2_match(),+or pcre2_dfa_match(). PCRE2_NO_UTF_CHECK affects only the function to which it+is passed. Put these bits at the most significant end of the options word so+others can be added next to them */++#define PCRE2_ANCHORED 0x80000000u+#define PCRE2_NO_UTF_CHECK 0x40000000u+#define PCRE2_ENDANCHORED 0x20000000u++/* The following option bits can be passed only to pcre2_compile(). However,+they may affect compilation, JIT compilation, and/or interpretive execution.+The following tags indicate which:++C alters what is compiled by pcre2_compile()+J alters what is compiled by pcre2_jit_compile()+M is inspected during pcre2_match() execution+D is inspected during pcre2_dfa_match() execution+*/++#define PCRE2_ALLOW_EMPTY_CLASS 0x00000001u /* C */+#define PCRE2_ALT_BSUX 0x00000002u /* C */+#define PCRE2_AUTO_CALLOUT 0x00000004u /* C */+#define PCRE2_CASELESS 0x00000008u /* C */+#define PCRE2_DOLLAR_ENDONLY 0x00000010u /* J M D */+#define PCRE2_DOTALL 0x00000020u /* C */+#define PCRE2_DUPNAMES 0x00000040u /* C */+#define PCRE2_EXTENDED 0x00000080u /* C */+#define PCRE2_FIRSTLINE 0x00000100u /* J M D */+#define PCRE2_MATCH_UNSET_BACKREF 0x00000200u /* C J M */+#define PCRE2_MULTILINE 0x00000400u /* C */+#define PCRE2_NEVER_UCP 0x00000800u /* C */+#define PCRE2_NEVER_UTF 0x00001000u /* C */+#define PCRE2_NO_AUTO_CAPTURE 0x00002000u /* C */+#define PCRE2_NO_AUTO_POSSESS 0x00004000u /* C */+#define PCRE2_NO_DOTSTAR_ANCHOR 0x00008000u /* C */+#define PCRE2_NO_START_OPTIMIZE 0x00010000u /* J M D */+#define PCRE2_UCP 0x00020000u /* C J M D */+#define PCRE2_UNGREEDY 0x00040000u /* C */+#define PCRE2_UTF 0x00080000u /* C J M D */+#define PCRE2_NEVER_BACKSLASH_C 0x00100000u /* C */+#define PCRE2_ALT_CIRCUMFLEX 0x00200000u /* J M D */+#define PCRE2_ALT_VERBNAMES 0x00400000u /* C */+#define PCRE2_USE_OFFSET_LIMIT 0x00800000u /* J M D */+#define PCRE2_EXTENDED_MORE 0x01000000u /* C */+#define PCRE2_LITERAL 0x02000000u /* C */+#define PCRE2_MATCH_INVALID_UTF 0x04000000u /* J M D */++/* An additional compile options word is available in the compile context. */++#define PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES 0x00000001u /* C */+#define PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL 0x00000002u /* C */+#define PCRE2_EXTRA_MATCH_WORD 0x00000004u /* C */+#define PCRE2_EXTRA_MATCH_LINE 0x00000008u /* C */+#define PCRE2_EXTRA_ESCAPED_CR_IS_LF 0x00000010u /* C */+#define PCRE2_EXTRA_ALT_BSUX 0x00000020u /* C */++/* These are for pcre2_jit_compile(). */++#define PCRE2_JIT_COMPLETE 0x00000001u /* For full matching */+#define PCRE2_JIT_PARTIAL_SOFT 0x00000002u+#define PCRE2_JIT_PARTIAL_HARD 0x00000004u+#define PCRE2_JIT_INVALID_UTF 0x00000100u++/* These are for pcre2_match(), pcre2_dfa_match(), pcre2_jit_match(), and+pcre2_substitute(). Some are allowed only for one of the functions, and in+these cases it is noted below. Note that PCRE2_ANCHORED, PCRE2_ENDANCHORED and+PCRE2_NO_UTF_CHECK can also be passed to these functions (though+pcre2_jit_match() ignores the latter since it bypasses all sanity checks). */++#define PCRE2_NOTBOL 0x00000001u+#define PCRE2_NOTEOL 0x00000002u+#define PCRE2_NOTEMPTY 0x00000004u /* ) These two must be kept */+#define PCRE2_NOTEMPTY_ATSTART 0x00000008u /* ) adjacent to each other. */+#define PCRE2_PARTIAL_SOFT 0x00000010u+#define PCRE2_PARTIAL_HARD 0x00000020u+#define PCRE2_DFA_RESTART 0x00000040u /* pcre2_dfa_match() only */+#define PCRE2_DFA_SHORTEST 0x00000080u /* pcre2_dfa_match() only */+#define PCRE2_SUBSTITUTE_GLOBAL 0x00000100u /* pcre2_substitute() only */+#define PCRE2_SUBSTITUTE_EXTENDED 0x00000200u /* pcre2_substitute() only */+#define PCRE2_SUBSTITUTE_UNSET_EMPTY 0x00000400u /* pcre2_substitute() only */+#define PCRE2_SUBSTITUTE_UNKNOWN_UNSET 0x00000800u /* pcre2_substitute() only */+#define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH 0x00001000u /* pcre2_substitute() only */+#define PCRE2_NO_JIT 0x00002000u /* Not for pcre2_dfa_match() */+#define PCRE2_COPY_MATCHED_SUBJECT 0x00004000u+#define PCRE2_SUBSTITUTE_LITERAL 0x00008000u /* pcre2_substitute() only */+#define PCRE2_SUBSTITUTE_MATCHED 0x00010000u /* pcre2_substitute() only */+#define PCRE2_SUBSTITUTE_REPLACEMENT_ONLY 0x00020000u /* pcre2_substitute() only */++/* Options for pcre2_pattern_convert(). */++#define PCRE2_CONVERT_UTF 0x00000001u+#define PCRE2_CONVERT_NO_UTF_CHECK 0x00000002u+#define PCRE2_CONVERT_POSIX_BASIC 0x00000004u+#define PCRE2_CONVERT_POSIX_EXTENDED 0x00000008u+#define PCRE2_CONVERT_GLOB 0x00000010u+#define PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR 0x00000030u+#define PCRE2_CONVERT_GLOB_NO_STARSTAR 0x00000050u++/* Newline and \R settings, for use in compile contexts. The newline values+must be kept in step with values set in config.h and both sets must all be+greater than zero. */++#define PCRE2_NEWLINE_CR 1+#define PCRE2_NEWLINE_LF 2+#define PCRE2_NEWLINE_CRLF 3+#define PCRE2_NEWLINE_ANY 4+#define PCRE2_NEWLINE_ANYCRLF 5+#define PCRE2_NEWLINE_NUL 6++#define PCRE2_BSR_UNICODE 1+#define PCRE2_BSR_ANYCRLF 2++/* Error codes for pcre2_compile(). Some of these are also used by+pcre2_pattern_convert(). */++#define PCRE2_ERROR_END_BACKSLASH 101+#define PCRE2_ERROR_END_BACKSLASH_C 102+#define PCRE2_ERROR_UNKNOWN_ESCAPE 103+#define PCRE2_ERROR_QUANTIFIER_OUT_OF_ORDER 104+#define PCRE2_ERROR_QUANTIFIER_TOO_BIG 105+#define PCRE2_ERROR_MISSING_SQUARE_BRACKET 106+#define PCRE2_ERROR_ESCAPE_INVALID_IN_CLASS 107+#define PCRE2_ERROR_CLASS_RANGE_ORDER 108+#define PCRE2_ERROR_QUANTIFIER_INVALID 109+#define PCRE2_ERROR_INTERNAL_UNEXPECTED_REPEAT 110+#define PCRE2_ERROR_INVALID_AFTER_PARENS_QUERY 111+#define PCRE2_ERROR_POSIX_CLASS_NOT_IN_CLASS 112+#define PCRE2_ERROR_POSIX_NO_SUPPORT_COLLATING 113+#define PCRE2_ERROR_MISSING_CLOSING_PARENTHESIS 114+#define PCRE2_ERROR_BAD_SUBPATTERN_REFERENCE 115+#define PCRE2_ERROR_NULL_PATTERN 116+#define PCRE2_ERROR_BAD_OPTIONS 117+#define PCRE2_ERROR_MISSING_COMMENT_CLOSING 118+#define PCRE2_ERROR_PARENTHESES_NEST_TOO_DEEP 119+#define PCRE2_ERROR_PATTERN_TOO_LARGE 120+#define PCRE2_ERROR_HEAP_FAILED 121+#define PCRE2_ERROR_UNMATCHED_CLOSING_PARENTHESIS 122+#define PCRE2_ERROR_INTERNAL_CODE_OVERFLOW 123+#define PCRE2_ERROR_MISSING_CONDITION_CLOSING 124+#define PCRE2_ERROR_LOOKBEHIND_NOT_FIXED_LENGTH 125+#define PCRE2_ERROR_ZERO_RELATIVE_REFERENCE 126+#define PCRE2_ERROR_TOO_MANY_CONDITION_BRANCHES 127+#define PCRE2_ERROR_CONDITION_ASSERTION_EXPECTED 128+#define PCRE2_ERROR_BAD_RELATIVE_REFERENCE 129+#define PCRE2_ERROR_UNKNOWN_POSIX_CLASS 130+#define PCRE2_ERROR_INTERNAL_STUDY_ERROR 131+#define PCRE2_ERROR_UNICODE_NOT_SUPPORTED 132+#define PCRE2_ERROR_PARENTHESES_STACK_CHECK 133+#define PCRE2_ERROR_CODE_POINT_TOO_BIG 134+#define PCRE2_ERROR_LOOKBEHIND_TOO_COMPLICATED 135+#define PCRE2_ERROR_LOOKBEHIND_INVALID_BACKSLASH_C 136+#define PCRE2_ERROR_UNSUPPORTED_ESCAPE_SEQUENCE 137+#define PCRE2_ERROR_CALLOUT_NUMBER_TOO_BIG 138+#define PCRE2_ERROR_MISSING_CALLOUT_CLOSING 139+#define PCRE2_ERROR_ESCAPE_INVALID_IN_VERB 140+#define PCRE2_ERROR_UNRECOGNIZED_AFTER_QUERY_P 141+#define PCRE2_ERROR_MISSING_NAME_TERMINATOR 142+#define PCRE2_ERROR_DUPLICATE_SUBPATTERN_NAME 143+#define PCRE2_ERROR_INVALID_SUBPATTERN_NAME 144+#define PCRE2_ERROR_UNICODE_PROPERTIES_UNAVAILABLE 145+#define PCRE2_ERROR_MALFORMED_UNICODE_PROPERTY 146+#define PCRE2_ERROR_UNKNOWN_UNICODE_PROPERTY 147+#define PCRE2_ERROR_SUBPATTERN_NAME_TOO_LONG 148+#define PCRE2_ERROR_TOO_MANY_NAMED_SUBPATTERNS 149+#define PCRE2_ERROR_CLASS_INVALID_RANGE 150+#define PCRE2_ERROR_OCTAL_BYTE_TOO_BIG 151+#define PCRE2_ERROR_INTERNAL_OVERRAN_WORKSPACE 152+#define PCRE2_ERROR_INTERNAL_MISSING_SUBPATTERN 153+#define PCRE2_ERROR_DEFINE_TOO_MANY_BRANCHES 154+#define PCRE2_ERROR_BACKSLASH_O_MISSING_BRACE 155+#define PCRE2_ERROR_INTERNAL_UNKNOWN_NEWLINE 156+#define PCRE2_ERROR_BACKSLASH_G_SYNTAX 157+#define PCRE2_ERROR_PARENS_QUERY_R_MISSING_CLOSING 158+/* Error 159 is obsolete and should now never occur */+#define PCRE2_ERROR_VERB_ARGUMENT_NOT_ALLOWED 159+#define PCRE2_ERROR_VERB_UNKNOWN 160+#define PCRE2_ERROR_SUBPATTERN_NUMBER_TOO_BIG 161+#define PCRE2_ERROR_SUBPATTERN_NAME_EXPECTED 162+#define PCRE2_ERROR_INTERNAL_PARSED_OVERFLOW 163+#define PCRE2_ERROR_INVALID_OCTAL 164+#define PCRE2_ERROR_SUBPATTERN_NAMES_MISMATCH 165+#define PCRE2_ERROR_MARK_MISSING_ARGUMENT 166+#define PCRE2_ERROR_INVALID_HEXADECIMAL 167+#define PCRE2_ERROR_BACKSLASH_C_SYNTAX 168+#define PCRE2_ERROR_BACKSLASH_K_SYNTAX 169+#define PCRE2_ERROR_INTERNAL_BAD_CODE_LOOKBEHINDS 170+#define PCRE2_ERROR_BACKSLASH_N_IN_CLASS 171+#define PCRE2_ERROR_CALLOUT_STRING_TOO_LONG 172+#define PCRE2_ERROR_UNICODE_DISALLOWED_CODE_POINT 173+#define PCRE2_ERROR_UTF_IS_DISABLED 174+#define PCRE2_ERROR_UCP_IS_DISABLED 175+#define PCRE2_ERROR_VERB_NAME_TOO_LONG 176+#define PCRE2_ERROR_BACKSLASH_U_CODE_POINT_TOO_BIG 177+#define PCRE2_ERROR_MISSING_OCTAL_OR_HEX_DIGITS 178+#define PCRE2_ERROR_VERSION_CONDITION_SYNTAX 179+#define PCRE2_ERROR_INTERNAL_BAD_CODE_AUTO_POSSESS 180+#define PCRE2_ERROR_CALLOUT_NO_STRING_DELIMITER 181+#define PCRE2_ERROR_CALLOUT_BAD_STRING_DELIMITER 182+#define PCRE2_ERROR_BACKSLASH_C_CALLER_DISABLED 183+#define PCRE2_ERROR_QUERY_BARJX_NEST_TOO_DEEP 184+#define PCRE2_ERROR_BACKSLASH_C_LIBRARY_DISABLED 185+#define PCRE2_ERROR_PATTERN_TOO_COMPLICATED 186+#define PCRE2_ERROR_LOOKBEHIND_TOO_LONG 187+#define PCRE2_ERROR_PATTERN_STRING_TOO_LONG 188+#define PCRE2_ERROR_INTERNAL_BAD_CODE 189+#define PCRE2_ERROR_INTERNAL_BAD_CODE_IN_SKIP 190+#define PCRE2_ERROR_NO_SURROGATES_IN_UTF16 191+#define PCRE2_ERROR_BAD_LITERAL_OPTIONS 192+#define PCRE2_ERROR_SUPPORTED_ONLY_IN_UNICODE 193+#define PCRE2_ERROR_INVALID_HYPHEN_IN_OPTIONS 194+#define PCRE2_ERROR_ALPHA_ASSERTION_UNKNOWN 195+#define PCRE2_ERROR_SCRIPT_RUN_NOT_AVAILABLE 196+#define PCRE2_ERROR_TOO_MANY_CAPTURES 197+#define PCRE2_ERROR_CONDITION_ATOMIC_ASSERTION_EXPECTED 198+++/* "Expected" matching error codes: no match and partial match. */++#define PCRE2_ERROR_NOMATCH (-1)+#define PCRE2_ERROR_PARTIAL (-2)++/* Error codes for UTF-8 validity checks */++#define PCRE2_ERROR_UTF8_ERR1 (-3)+#define PCRE2_ERROR_UTF8_ERR2 (-4)+#define PCRE2_ERROR_UTF8_ERR3 (-5)+#define PCRE2_ERROR_UTF8_ERR4 (-6)+#define PCRE2_ERROR_UTF8_ERR5 (-7)+#define PCRE2_ERROR_UTF8_ERR6 (-8)+#define PCRE2_ERROR_UTF8_ERR7 (-9)+#define PCRE2_ERROR_UTF8_ERR8 (-10)+#define PCRE2_ERROR_UTF8_ERR9 (-11)+#define PCRE2_ERROR_UTF8_ERR10 (-12)+#define PCRE2_ERROR_UTF8_ERR11 (-13)+#define PCRE2_ERROR_UTF8_ERR12 (-14)+#define PCRE2_ERROR_UTF8_ERR13 (-15)+#define PCRE2_ERROR_UTF8_ERR14 (-16)+#define PCRE2_ERROR_UTF8_ERR15 (-17)+#define PCRE2_ERROR_UTF8_ERR16 (-18)+#define PCRE2_ERROR_UTF8_ERR17 (-19)+#define PCRE2_ERROR_UTF8_ERR18 (-20)+#define PCRE2_ERROR_UTF8_ERR19 (-21)+#define PCRE2_ERROR_UTF8_ERR20 (-22)+#define PCRE2_ERROR_UTF8_ERR21 (-23)++/* Error codes for UTF-16 validity checks */++#define PCRE2_ERROR_UTF16_ERR1 (-24)+#define PCRE2_ERROR_UTF16_ERR2 (-25)+#define PCRE2_ERROR_UTF16_ERR3 (-26)++/* Error codes for UTF-32 validity checks */++#define PCRE2_ERROR_UTF32_ERR1 (-27)+#define PCRE2_ERROR_UTF32_ERR2 (-28)++/* Miscellaneous error codes for pcre2[_dfa]_match(), substring extraction+functions, context functions, and serializing functions. They are in numerical+order. Originally they were in alphabetical order too, but now that PCRE2 is+released, the numbers must not be changed. */++#define PCRE2_ERROR_BADDATA (-29)+#define PCRE2_ERROR_MIXEDTABLES (-30) /* Name was changed */+#define PCRE2_ERROR_BADMAGIC (-31)+#define PCRE2_ERROR_BADMODE (-32)+#define PCRE2_ERROR_BADOFFSET (-33)+#define PCRE2_ERROR_BADOPTION (-34)+#define PCRE2_ERROR_BADREPLACEMENT (-35)+#define PCRE2_ERROR_BADUTFOFFSET (-36)+#define PCRE2_ERROR_CALLOUT (-37) /* Never used by PCRE2 itself */+#define PCRE2_ERROR_DFA_BADRESTART (-38)+#define PCRE2_ERROR_DFA_RECURSE (-39)+#define PCRE2_ERROR_DFA_UCOND (-40)+#define PCRE2_ERROR_DFA_UFUNC (-41)+#define PCRE2_ERROR_DFA_UITEM (-42)+#define PCRE2_ERROR_DFA_WSSIZE (-43)+#define PCRE2_ERROR_INTERNAL (-44)+#define PCRE2_ERROR_JIT_BADOPTION (-45)+#define PCRE2_ERROR_JIT_STACKLIMIT (-46)+#define PCRE2_ERROR_MATCHLIMIT (-47)+#define PCRE2_ERROR_NOMEMORY (-48)+#define PCRE2_ERROR_NOSUBSTRING (-49)+#define PCRE2_ERROR_NOUNIQUESUBSTRING (-50)+#define PCRE2_ERROR_NULL (-51)+#define PCRE2_ERROR_RECURSELOOP (-52)+#define PCRE2_ERROR_DEPTHLIMIT (-53)+#define PCRE2_ERROR_RECURSIONLIMIT (-53) /* Obsolete synonym */+#define PCRE2_ERROR_UNAVAILABLE (-54)+#define PCRE2_ERROR_UNSET (-55)+#define PCRE2_ERROR_BADOFFSETLIMIT (-56)+#define PCRE2_ERROR_BADREPESCAPE (-57)+#define PCRE2_ERROR_REPMISSINGBRACE (-58)+#define PCRE2_ERROR_BADSUBSTITUTION (-59)+#define PCRE2_ERROR_BADSUBSPATTERN (-60)+#define PCRE2_ERROR_TOOMANYREPLACE (-61)+#define PCRE2_ERROR_BADSERIALIZEDDATA (-62)+#define PCRE2_ERROR_HEAPLIMIT (-63)+#define PCRE2_ERROR_CONVERT_SYNTAX (-64)+#define PCRE2_ERROR_INTERNAL_DUPMATCH (-65)+#define PCRE2_ERROR_DFA_UINVALID_UTF (-66)+++/* Request types for pcre2_pattern_info() */++#define PCRE2_INFO_ALLOPTIONS 0+#define PCRE2_INFO_ARGOPTIONS 1+#define PCRE2_INFO_BACKREFMAX 2+#define PCRE2_INFO_BSR 3+#define PCRE2_INFO_CAPTURECOUNT 4+#define PCRE2_INFO_FIRSTCODEUNIT 5+#define PCRE2_INFO_FIRSTCODETYPE 6+#define PCRE2_INFO_FIRSTBITMAP 7+#define PCRE2_INFO_HASCRORLF 8+#define PCRE2_INFO_JCHANGED 9+#define PCRE2_INFO_JITSIZE 10+#define PCRE2_INFO_LASTCODEUNIT 11+#define PCRE2_INFO_LASTCODETYPE 12+#define PCRE2_INFO_MATCHEMPTY 13+#define PCRE2_INFO_MATCHLIMIT 14+#define PCRE2_INFO_MAXLOOKBEHIND 15+#define PCRE2_INFO_MINLENGTH 16+#define PCRE2_INFO_NAMECOUNT 17+#define PCRE2_INFO_NAMEENTRYSIZE 18+#define PCRE2_INFO_NAMETABLE 19+#define PCRE2_INFO_NEWLINE 20+#define PCRE2_INFO_DEPTHLIMIT 21+#define PCRE2_INFO_RECURSIONLIMIT 21 /* Obsolete synonym */+#define PCRE2_INFO_SIZE 22+#define PCRE2_INFO_HASBACKSLASHC 23+#define PCRE2_INFO_FRAMESIZE 24+#define PCRE2_INFO_HEAPLIMIT 25+#define PCRE2_INFO_EXTRAOPTIONS 26++/* Request types for pcre2_config(). */++#define PCRE2_CONFIG_BSR 0+#define PCRE2_CONFIG_JIT 1+#define PCRE2_CONFIG_JITTARGET 2+#define PCRE2_CONFIG_LINKSIZE 3+#define PCRE2_CONFIG_MATCHLIMIT 4+#define PCRE2_CONFIG_NEWLINE 5+#define PCRE2_CONFIG_PARENSLIMIT 6+#define PCRE2_CONFIG_DEPTHLIMIT 7+#define PCRE2_CONFIG_RECURSIONLIMIT 7 /* Obsolete synonym */+#define PCRE2_CONFIG_STACKRECURSE 8 /* Obsolete */+#define PCRE2_CONFIG_UNICODE 9+#define PCRE2_CONFIG_UNICODE_VERSION 10+#define PCRE2_CONFIG_VERSION 11+#define PCRE2_CONFIG_HEAPLIMIT 12+#define PCRE2_CONFIG_NEVER_BACKSLASH_C 13+#define PCRE2_CONFIG_COMPILED_WIDTHS 14+#define PCRE2_CONFIG_TABLES_LENGTH 15+++/* Types for code units in patterns and subject strings. */++typedef uint8_t PCRE2_UCHAR8;+typedef uint16_t PCRE2_UCHAR16;+typedef uint32_t PCRE2_UCHAR32;++typedef const PCRE2_UCHAR8 *PCRE2_SPTR8;+typedef const PCRE2_UCHAR16 *PCRE2_SPTR16;+typedef const PCRE2_UCHAR32 *PCRE2_SPTR32;++/* The PCRE2_SIZE type is used for all string lengths and offsets in PCRE2,+including pattern offsets for errors and subject offsets after a match. We+define special values to indicate zero-terminated strings and unset offsets in+the offset vector (ovector). */++#define PCRE2_SIZE size_t+#define PCRE2_SIZE_MAX SIZE_MAX+#define PCRE2_ZERO_TERMINATED (~(PCRE2_SIZE)0)+#define PCRE2_UNSET (~(PCRE2_SIZE)0)++/* Generic types for opaque structures and JIT callback functions. These+declarations are defined in a macro that is expanded for each width later. */++#define PCRE2_TYPES_LIST \+struct pcre2_real_general_context; \+typedef struct pcre2_real_general_context pcre2_general_context; \+\+struct pcre2_real_compile_context; \+typedef struct pcre2_real_compile_context pcre2_compile_context; \+\+struct pcre2_real_match_context; \+typedef struct pcre2_real_match_context pcre2_match_context; \+\+struct pcre2_real_convert_context; \+typedef struct pcre2_real_convert_context pcre2_convert_context; \+\+struct pcre2_real_code; \+typedef struct pcre2_real_code pcre2_code; \+\+struct pcre2_real_match_data; \+typedef struct pcre2_real_match_data pcre2_match_data; \+\+struct pcre2_real_jit_stack; \+typedef struct pcre2_real_jit_stack pcre2_jit_stack; \+\+typedef pcre2_jit_stack *(*pcre2_jit_callback)(void *);+++/* The structures for passing out data via callout functions. We use structures+so that new fields can be added on the end in future versions, without changing+the API of the function, thereby allowing old clients to work without+modification. Define the generic versions in a macro; the width-specific+versions are generated from this macro below. */++/* Flags for the callout_flags field. These are cleared after a callout. */++#define PCRE2_CALLOUT_STARTMATCH 0x00000001u /* Set for each bumpalong */+#define PCRE2_CALLOUT_BACKTRACK 0x00000002u /* Set after a backtrack */++#define PCRE2_STRUCTURE_LIST \+typedef struct pcre2_callout_block { \+ uint32_t version; /* Identifies version of block */ \+ /* ------------------------ Version 0 ------------------------------- */ \+ uint32_t callout_number; /* Number compiled into pattern */ \+ uint32_t capture_top; /* Max current capture */ \+ uint32_t capture_last; /* Most recently closed capture */ \+ PCRE2_SIZE *offset_vector; /* The offset vector */ \+ PCRE2_SPTR mark; /* Pointer to current mark or NULL */ \+ PCRE2_SPTR subject; /* The subject being matched */ \+ PCRE2_SIZE subject_length; /* The length of the subject */ \+ PCRE2_SIZE start_match; /* Offset to start of this match attempt */ \+ PCRE2_SIZE current_position; /* Where we currently are in the subject */ \+ PCRE2_SIZE pattern_position; /* Offset to next item in the pattern */ \+ PCRE2_SIZE next_item_length; /* Length of next item in the pattern */ \+ /* ------------------- Added for Version 1 -------------------------- */ \+ PCRE2_SIZE callout_string_offset; /* Offset to string within pattern */ \+ PCRE2_SIZE callout_string_length; /* Length of string compiled into pattern */ \+ PCRE2_SPTR callout_string; /* String compiled into pattern */ \+ /* ------------------- Added for Version 2 -------------------------- */ \+ uint32_t callout_flags; /* See above for list */ \+ /* ------------------------------------------------------------------ */ \+} pcre2_callout_block; \+\+typedef struct pcre2_callout_enumerate_block { \+ uint32_t version; /* Identifies version of block */ \+ /* ------------------------ Version 0 ------------------------------- */ \+ PCRE2_SIZE pattern_position; /* Offset to next item in the pattern */ \+ PCRE2_SIZE next_item_length; /* Length of next item in the pattern */ \+ uint32_t callout_number; /* Number compiled into pattern */ \+ PCRE2_SIZE callout_string_offset; /* Offset to string within pattern */ \+ PCRE2_SIZE callout_string_length; /* Length of string compiled into pattern */ \+ PCRE2_SPTR callout_string; /* String compiled into pattern */ \+ /* ------------------------------------------------------------------ */ \+} pcre2_callout_enumerate_block; \+\+typedef struct pcre2_substitute_callout_block { \+ uint32_t version; /* Identifies version of block */ \+ /* ------------------------ Version 0 ------------------------------- */ \+ PCRE2_SPTR input; /* Pointer to input subject string */ \+ PCRE2_SPTR output; /* Pointer to output buffer */ \+ PCRE2_SIZE output_offsets[2]; /* Changed portion of the output */ \+ PCRE2_SIZE *ovector; /* Pointer to current ovector */ \+ uint32_t oveccount; /* Count of pairs set in ovector */ \+ uint32_t subscount; /* Substitution number */ \+ /* ------------------------------------------------------------------ */ \+} pcre2_substitute_callout_block;+++/* List the generic forms of all other functions in macros, which will be+expanded for each width below. Start with functions that give general+information. */++#define PCRE2_GENERAL_INFO_FUNCTIONS \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION pcre2_config(uint32_t, void *);+++/* Functions for manipulating contexts. */++#define PCRE2_GENERAL_CONTEXT_FUNCTIONS \+PCRE2_EXP_DECL pcre2_general_context PCRE2_CALL_CONVENTION \+ *pcre2_general_context_copy(pcre2_general_context *); \+PCRE2_EXP_DECL pcre2_general_context PCRE2_CALL_CONVENTION \+ *pcre2_general_context_create(void *(*)(PCRE2_SIZE, void *), \+ void (*)(void *, void *), void *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_general_context_free(pcre2_general_context *);++#define PCRE2_COMPILE_CONTEXT_FUNCTIONS \+PCRE2_EXP_DECL pcre2_compile_context PCRE2_CALL_CONVENTION \+ *pcre2_compile_context_copy(pcre2_compile_context *); \+PCRE2_EXP_DECL pcre2_compile_context PCRE2_CALL_CONVENTION \+ *pcre2_compile_context_create(pcre2_general_context *);\+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_compile_context_free(pcre2_compile_context *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_bsr(pcre2_compile_context *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_character_tables(pcre2_compile_context *, const uint8_t *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_compile_extra_options(pcre2_compile_context *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_max_pattern_length(pcre2_compile_context *, PCRE2_SIZE); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_newline(pcre2_compile_context *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_parens_nest_limit(pcre2_compile_context *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_compile_recursion_guard(pcre2_compile_context *, \+ int (*)(uint32_t, void *), void *);++#define PCRE2_MATCH_CONTEXT_FUNCTIONS \+PCRE2_EXP_DECL pcre2_match_context PCRE2_CALL_CONVENTION \+ *pcre2_match_context_copy(pcre2_match_context *); \+PCRE2_EXP_DECL pcre2_match_context PCRE2_CALL_CONVENTION \+ *pcre2_match_context_create(pcre2_general_context *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_match_context_free(pcre2_match_context *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_callout(pcre2_match_context *, \+ int (*)(pcre2_callout_block *, void *), void *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_substitute_callout(pcre2_match_context *, \+ int (*)(pcre2_substitute_callout_block *, void *), void *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_depth_limit(pcre2_match_context *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_heap_limit(pcre2_match_context *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_match_limit(pcre2_match_context *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_offset_limit(pcre2_match_context *, PCRE2_SIZE); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_recursion_limit(pcre2_match_context *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_recursion_memory_management(pcre2_match_context *, \+ void *(*)(PCRE2_SIZE, void *), void (*)(void *, void *), void *);++#define PCRE2_CONVERT_CONTEXT_FUNCTIONS \+PCRE2_EXP_DECL pcre2_convert_context PCRE2_CALL_CONVENTION \+ *pcre2_convert_context_copy(pcre2_convert_context *); \+PCRE2_EXP_DECL pcre2_convert_context PCRE2_CALL_CONVENTION \+ *pcre2_convert_context_create(pcre2_general_context *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_convert_context_free(pcre2_convert_context *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_glob_escape(pcre2_convert_context *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_glob_separator(pcre2_convert_context *, uint32_t);+++/* Functions concerned with compiling a pattern to PCRE internal code. */++#define PCRE2_COMPILE_FUNCTIONS \+PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \+ *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, \+ pcre2_compile_context *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_code_free(pcre2_code *); \+PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \+ *pcre2_code_copy(const pcre2_code *); \+PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \+ *pcre2_code_copy_with_tables(const pcre2_code *);+++/* Functions that give information about a compiled pattern. */++#define PCRE2_PATTERN_INFO_FUNCTIONS \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_pattern_info(const pcre2_code *, uint32_t, void *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_callout_enumerate(const pcre2_code *, \+ int (*)(pcre2_callout_enumerate_block *, void *), void *);+++/* Functions for running a match and inspecting the result. */++#define PCRE2_MATCH_FUNCTIONS \+PCRE2_EXP_DECL pcre2_match_data PCRE2_CALL_CONVENTION \+ *pcre2_match_data_create(uint32_t, pcre2_general_context *); \+PCRE2_EXP_DECL pcre2_match_data PCRE2_CALL_CONVENTION \+ *pcre2_match_data_create_from_pattern(const pcre2_code *, \+ pcre2_general_context *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_dfa_match(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \+ uint32_t, pcre2_match_data *, pcre2_match_context *, int *, PCRE2_SIZE); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_match(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \+ uint32_t, pcre2_match_data *, pcre2_match_context *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_match_data_free(pcre2_match_data *); \+PCRE2_EXP_DECL PCRE2_SPTR PCRE2_CALL_CONVENTION \+ pcre2_get_mark(pcre2_match_data *); \+PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \+ pcre2_get_match_data_size(pcre2_match_data *); \+PCRE2_EXP_DECL uint32_t PCRE2_CALL_CONVENTION \+ pcre2_get_ovector_count(pcre2_match_data *); \+PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \+ *pcre2_get_ovector_pointer(pcre2_match_data *); \+PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \+ pcre2_get_startchar(pcre2_match_data *);+++/* Convenience functions for handling matched substrings. */++#define PCRE2_SUBSTRING_FUNCTIONS \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_substring_copy_byname(pcre2_match_data *, PCRE2_SPTR, PCRE2_UCHAR *, \+ PCRE2_SIZE *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_substring_copy_bynumber(pcre2_match_data *, uint32_t, PCRE2_UCHAR *, \+ PCRE2_SIZE *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_substring_free(PCRE2_UCHAR *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_substring_get_byname(pcre2_match_data *, PCRE2_SPTR, PCRE2_UCHAR **, \+ PCRE2_SIZE *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_substring_get_bynumber(pcre2_match_data *, uint32_t, PCRE2_UCHAR **, \+ PCRE2_SIZE *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_substring_length_byname(pcre2_match_data *, PCRE2_SPTR, PCRE2_SIZE *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_substring_length_bynumber(pcre2_match_data *, uint32_t, PCRE2_SIZE *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_substring_nametable_scan(const pcre2_code *, PCRE2_SPTR, PCRE2_SPTR *, \+ PCRE2_SPTR *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_substring_number_from_name(const pcre2_code *, PCRE2_SPTR); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_substring_list_free(PCRE2_SPTR *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_substring_list_get(pcre2_match_data *, PCRE2_UCHAR ***, PCRE2_SIZE **);++/* Functions for serializing / deserializing compiled patterns. */++#define PCRE2_SERIALIZE_FUNCTIONS \+PCRE2_EXP_DECL int32_t PCRE2_CALL_CONVENTION \+ pcre2_serialize_encode(const pcre2_code **, int32_t, uint8_t **, \+ PCRE2_SIZE *, pcre2_general_context *); \+PCRE2_EXP_DECL int32_t PCRE2_CALL_CONVENTION \+ pcre2_serialize_decode(pcre2_code **, int32_t, const uint8_t *, \+ pcre2_general_context *); \+PCRE2_EXP_DECL int32_t PCRE2_CALL_CONVENTION \+ pcre2_serialize_get_number_of_codes(const uint8_t *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_serialize_free(uint8_t *);+++/* Convenience function for match + substitute. */++#define PCRE2_SUBSTITUTE_FUNCTION \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_substitute(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \+ uint32_t, pcre2_match_data *, pcre2_match_context *, PCRE2_SPTR, \+ PCRE2_SIZE, PCRE2_UCHAR *, PCRE2_SIZE *);+++/* Functions for converting pattern source strings. */++#define PCRE2_CONVERT_FUNCTIONS \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_pattern_convert(PCRE2_SPTR, PCRE2_SIZE, uint32_t, PCRE2_UCHAR **, \+ PCRE2_SIZE *, pcre2_convert_context *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_converted_pattern_free(PCRE2_UCHAR *);+++/* Functions for JIT processing */++#define PCRE2_JIT_FUNCTIONS \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_jit_compile(pcre2_code *, uint32_t); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_jit_match(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \+ uint32_t, pcre2_match_data *, pcre2_match_context *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_jit_free_unused_memory(pcre2_general_context *); \+PCRE2_EXP_DECL pcre2_jit_stack PCRE2_CALL_CONVENTION \+ *pcre2_jit_stack_create(PCRE2_SIZE, PCRE2_SIZE, pcre2_general_context *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_jit_stack_assign(pcre2_match_context *, pcre2_jit_callback, void *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_jit_stack_free(pcre2_jit_stack *);+++/* Other miscellaneous functions. */++#define PCRE2_OTHER_FUNCTIONS \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_get_error_message(int, PCRE2_UCHAR *, PCRE2_SIZE); \+PCRE2_EXP_DECL const uint8_t PCRE2_CALL_CONVENTION \+ *pcre2_maketables(pcre2_general_context *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_maketables_free(pcre2_general_context *, const uint8_t *);++/* Define macros that generate width-specific names from generic versions. The+three-level macro scheme is necessary to get the macros expanded when we want+them to be. First we get the width from PCRE2_LOCAL_WIDTH, which is used for+generating three versions of everything below. After that, PCRE2_SUFFIX will be+re-defined to use PCRE2_CODE_UNIT_WIDTH, for use when macros such as+pcre2_compile are called by application code. */++#define PCRE2_JOIN(a,b) a ## b+#define PCRE2_GLUE(a,b) PCRE2_JOIN(a,b)+#define PCRE2_SUFFIX(a) PCRE2_GLUE(a,PCRE2_LOCAL_WIDTH)+++/* Data types */++#define PCRE2_UCHAR PCRE2_SUFFIX(PCRE2_UCHAR)+#define PCRE2_SPTR PCRE2_SUFFIX(PCRE2_SPTR)++#define pcre2_code PCRE2_SUFFIX(pcre2_code_)+#define pcre2_jit_callback PCRE2_SUFFIX(pcre2_jit_callback_)+#define pcre2_jit_stack PCRE2_SUFFIX(pcre2_jit_stack_)++#define pcre2_real_code PCRE2_SUFFIX(pcre2_real_code_)+#define pcre2_real_general_context PCRE2_SUFFIX(pcre2_real_general_context_)+#define pcre2_real_compile_context PCRE2_SUFFIX(pcre2_real_compile_context_)+#define pcre2_real_convert_context PCRE2_SUFFIX(pcre2_real_convert_context_)+#define pcre2_real_match_context PCRE2_SUFFIX(pcre2_real_match_context_)+#define pcre2_real_jit_stack PCRE2_SUFFIX(pcre2_real_jit_stack_)+#define pcre2_real_match_data PCRE2_SUFFIX(pcre2_real_match_data_)+++/* Data blocks */++#define pcre2_callout_block PCRE2_SUFFIX(pcre2_callout_block_)+#define pcre2_callout_enumerate_block PCRE2_SUFFIX(pcre2_callout_enumerate_block_)+#define pcre2_substitute_callout_block PCRE2_SUFFIX(pcre2_substitute_callout_block_)+#define pcre2_general_context PCRE2_SUFFIX(pcre2_general_context_)+#define pcre2_compile_context PCRE2_SUFFIX(pcre2_compile_context_)+#define pcre2_convert_context PCRE2_SUFFIX(pcre2_convert_context_)+#define pcre2_match_context PCRE2_SUFFIX(pcre2_match_context_)+#define pcre2_match_data PCRE2_SUFFIX(pcre2_match_data_)+++/* Functions: the complete list in alphabetical order */++#define pcre2_callout_enumerate PCRE2_SUFFIX(pcre2_callout_enumerate_)+#define pcre2_code_copy PCRE2_SUFFIX(pcre2_code_copy_)+#define pcre2_code_copy_with_tables PCRE2_SUFFIX(pcre2_code_copy_with_tables_)+#define pcre2_code_free PCRE2_SUFFIX(pcre2_code_free_)+#define pcre2_compile PCRE2_SUFFIX(pcre2_compile_)+#define pcre2_compile_context_copy PCRE2_SUFFIX(pcre2_compile_context_copy_)+#define pcre2_compile_context_create PCRE2_SUFFIX(pcre2_compile_context_create_)+#define pcre2_compile_context_free PCRE2_SUFFIX(pcre2_compile_context_free_)+#define pcre2_config PCRE2_SUFFIX(pcre2_config_)+#define pcre2_convert_context_copy PCRE2_SUFFIX(pcre2_convert_context_copy_)+#define pcre2_convert_context_create PCRE2_SUFFIX(pcre2_convert_context_create_)+#define pcre2_convert_context_free PCRE2_SUFFIX(pcre2_convert_context_free_)+#define pcre2_converted_pattern_free PCRE2_SUFFIX(pcre2_converted_pattern_free_)+#define pcre2_dfa_match PCRE2_SUFFIX(pcre2_dfa_match_)+#define pcre2_general_context_copy PCRE2_SUFFIX(pcre2_general_context_copy_)+#define pcre2_general_context_create PCRE2_SUFFIX(pcre2_general_context_create_)+#define pcre2_general_context_free PCRE2_SUFFIX(pcre2_general_context_free_)+#define pcre2_get_error_message PCRE2_SUFFIX(pcre2_get_error_message_)+#define pcre2_get_mark PCRE2_SUFFIX(pcre2_get_mark_)+#define pcre2_get_match_data_size PCRE2_SUFFIX(pcre2_get_match_data_size_)+#define pcre2_get_ovector_pointer PCRE2_SUFFIX(pcre2_get_ovector_pointer_)+#define pcre2_get_ovector_count PCRE2_SUFFIX(pcre2_get_ovector_count_)+#define pcre2_get_startchar PCRE2_SUFFIX(pcre2_get_startchar_)+#define pcre2_jit_compile PCRE2_SUFFIX(pcre2_jit_compile_)+#define pcre2_jit_match PCRE2_SUFFIX(pcre2_jit_match_)+#define pcre2_jit_free_unused_memory PCRE2_SUFFIX(pcre2_jit_free_unused_memory_)+#define pcre2_jit_stack_assign PCRE2_SUFFIX(pcre2_jit_stack_assign_)+#define pcre2_jit_stack_create PCRE2_SUFFIX(pcre2_jit_stack_create_)+#define pcre2_jit_stack_free PCRE2_SUFFIX(pcre2_jit_stack_free_)+#define pcre2_maketables PCRE2_SUFFIX(pcre2_maketables_)+#define pcre2_maketables_free PCRE2_SUFFIX(pcre2_maketables_free_)+#define pcre2_match PCRE2_SUFFIX(pcre2_match_)+#define pcre2_match_context_copy PCRE2_SUFFIX(pcre2_match_context_copy_)+#define pcre2_match_context_create PCRE2_SUFFIX(pcre2_match_context_create_)+#define pcre2_match_context_free PCRE2_SUFFIX(pcre2_match_context_free_)+#define pcre2_match_data_create PCRE2_SUFFIX(pcre2_match_data_create_)+#define pcre2_match_data_create_from_pattern PCRE2_SUFFIX(pcre2_match_data_create_from_pattern_)+#define pcre2_match_data_free PCRE2_SUFFIX(pcre2_match_data_free_)+#define pcre2_pattern_convert PCRE2_SUFFIX(pcre2_pattern_convert_)+#define pcre2_pattern_info PCRE2_SUFFIX(pcre2_pattern_info_)+#define pcre2_serialize_decode PCRE2_SUFFIX(pcre2_serialize_decode_)+#define pcre2_serialize_encode PCRE2_SUFFIX(pcre2_serialize_encode_)+#define pcre2_serialize_free PCRE2_SUFFIX(pcre2_serialize_free_)+#define pcre2_serialize_get_number_of_codes PCRE2_SUFFIX(pcre2_serialize_get_number_of_codes_)+#define pcre2_set_bsr PCRE2_SUFFIX(pcre2_set_bsr_)+#define pcre2_set_callout PCRE2_SUFFIX(pcre2_set_callout_)+#define pcre2_set_character_tables PCRE2_SUFFIX(pcre2_set_character_tables_)+#define pcre2_set_compile_extra_options PCRE2_SUFFIX(pcre2_set_compile_extra_options_)+#define pcre2_set_compile_recursion_guard PCRE2_SUFFIX(pcre2_set_compile_recursion_guard_)+#define pcre2_set_depth_limit PCRE2_SUFFIX(pcre2_set_depth_limit_)+#define pcre2_set_glob_escape PCRE2_SUFFIX(pcre2_set_glob_escape_)+#define pcre2_set_glob_separator PCRE2_SUFFIX(pcre2_set_glob_separator_)+#define pcre2_set_heap_limit PCRE2_SUFFIX(pcre2_set_heap_limit_)+#define pcre2_set_match_limit PCRE2_SUFFIX(pcre2_set_match_limit_)+#define pcre2_set_max_pattern_length PCRE2_SUFFIX(pcre2_set_max_pattern_length_)+#define pcre2_set_newline PCRE2_SUFFIX(pcre2_set_newline_)+#define pcre2_set_parens_nest_limit PCRE2_SUFFIX(pcre2_set_parens_nest_limit_)+#define pcre2_set_offset_limit PCRE2_SUFFIX(pcre2_set_offset_limit_)+#define pcre2_set_substitute_callout PCRE2_SUFFIX(pcre2_set_substitute_callout_)+#define pcre2_substitute PCRE2_SUFFIX(pcre2_substitute_)+#define pcre2_substring_copy_byname PCRE2_SUFFIX(pcre2_substring_copy_byname_)+#define pcre2_substring_copy_bynumber PCRE2_SUFFIX(pcre2_substring_copy_bynumber_)+#define pcre2_substring_free PCRE2_SUFFIX(pcre2_substring_free_)+#define pcre2_substring_get_byname PCRE2_SUFFIX(pcre2_substring_get_byname_)+#define pcre2_substring_get_bynumber PCRE2_SUFFIX(pcre2_substring_get_bynumber_)+#define pcre2_substring_length_byname PCRE2_SUFFIX(pcre2_substring_length_byname_)+#define pcre2_substring_length_bynumber PCRE2_SUFFIX(pcre2_substring_length_bynumber_)+#define pcre2_substring_list_get PCRE2_SUFFIX(pcre2_substring_list_get_)+#define pcre2_substring_list_free PCRE2_SUFFIX(pcre2_substring_list_free_)+#define pcre2_substring_nametable_scan PCRE2_SUFFIX(pcre2_substring_nametable_scan_)+#define pcre2_substring_number_from_name PCRE2_SUFFIX(pcre2_substring_number_from_name_)++/* Keep this old function name for backwards compatibility */+#define pcre2_set_recursion_limit PCRE2_SUFFIX(pcre2_set_recursion_limit_)++/* Keep this obsolete function for backwards compatibility: it is now a noop. */+#define pcre2_set_recursion_memory_management PCRE2_SUFFIX(pcre2_set_recursion_memory_management_)++/* Now generate all three sets of width-specific structures and function+prototypes. */++#define PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS \+PCRE2_TYPES_LIST \+PCRE2_STRUCTURE_LIST \+PCRE2_GENERAL_INFO_FUNCTIONS \+PCRE2_GENERAL_CONTEXT_FUNCTIONS \+PCRE2_COMPILE_CONTEXT_FUNCTIONS \+PCRE2_CONVERT_CONTEXT_FUNCTIONS \+PCRE2_CONVERT_FUNCTIONS \+PCRE2_MATCH_CONTEXT_FUNCTIONS \+PCRE2_COMPILE_FUNCTIONS \+PCRE2_PATTERN_INFO_FUNCTIONS \+PCRE2_MATCH_FUNCTIONS \+PCRE2_SUBSTRING_FUNCTIONS \+PCRE2_SERIALIZE_FUNCTIONS \+PCRE2_SUBSTITUTE_FUNCTION \+PCRE2_JIT_FUNCTIONS \+PCRE2_OTHER_FUNCTIONS++#define PCRE2_LOCAL_WIDTH 8+PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS+#undef PCRE2_LOCAL_WIDTH++#define PCRE2_LOCAL_WIDTH 16+PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS+#undef PCRE2_LOCAL_WIDTH++#define PCRE2_LOCAL_WIDTH 32+PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS+#undef PCRE2_LOCAL_WIDTH++/* Undefine the list macros; they are no longer needed. */++#undef PCRE2_TYPES_LIST+#undef PCRE2_STRUCTURE_LIST+#undef PCRE2_GENERAL_INFO_FUNCTIONS+#undef PCRE2_GENERAL_CONTEXT_FUNCTIONS+#undef PCRE2_COMPILE_CONTEXT_FUNCTIONS+#undef PCRE2_CONVERT_CONTEXT_FUNCTIONS+#undef PCRE2_MATCH_CONTEXT_FUNCTIONS+#undef PCRE2_COMPILE_FUNCTIONS+#undef PCRE2_PATTERN_INFO_FUNCTIONS+#undef PCRE2_MATCH_FUNCTIONS+#undef PCRE2_SUBSTRING_FUNCTIONS+#undef PCRE2_SERIALIZE_FUNCTIONS+#undef PCRE2_SUBSTITUTE_FUNCTION+#undef PCRE2_JIT_FUNCTIONS+#undef PCRE2_OTHER_FUNCTIONS+#undef PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS++/* PCRE2_CODE_UNIT_WIDTH must be defined. If it is 8, 16, or 32, redefine+PCRE2_SUFFIX to use it. If it is 0, undefine the other macros and make+PCRE2_SUFFIX a no-op. Otherwise, generate an error. */++#undef PCRE2_SUFFIX+#ifndef PCRE2_CODE_UNIT_WIDTH+#error PCRE2_CODE_UNIT_WIDTH must be defined before including pcre2.h.+#error Use 8, 16, or 32; or 0 for a multi-width application.+#else /* PCRE2_CODE_UNIT_WIDTH is defined */+#if PCRE2_CODE_UNIT_WIDTH == 8 || \+ PCRE2_CODE_UNIT_WIDTH == 16 || \+ PCRE2_CODE_UNIT_WIDTH == 32+#define PCRE2_SUFFIX(a) PCRE2_GLUE(a, PCRE2_CODE_UNIT_WIDTH)+#elif PCRE2_CODE_UNIT_WIDTH == 0+#undef PCRE2_JOIN+#undef PCRE2_GLUE+#define PCRE2_SUFFIX(a) a+#else+#error PCRE2_CODE_UNIT_WIDTH must be 0, 8, 16, or 32.+#endif+#endif /* PCRE2_CODE_UNIT_WIDTH is defined */++#ifdef __cplusplus+} /* extern "C" */+#endif++#endif /* PCRE2_H_IDEMPOTENT_GUARD */++/* End of pcre2.h */
+ src/c/pcre2/maint/ucptest.c view
@@ -0,0 +1,828 @@+/***************************************************+* A program for testing the Unicode property table *+***************************************************/++/* Copyright (c) University of Cambridge 2008-2020 */++/* Compile thus:++ gcc -DHAVE_CONFIG_H -DPCRE2_CODE_UNIT_WIDTH=8 -o ucptest \+ ucptest.c ../src/pcre2_ucd.c ../src/pcre2_tables.c++ Add -lreadline or -ledit if PCRE2 was configured with readline or libedit+ support in pcre2test.+*/++/* This is a hacked-up program for testing the Unicode properties tables of+PCRE2. It can also be used for finding characters with certain properties.+I wrote it to help with debugging PCRE, and have added things that I found+useful, in a rather haphazard way. The code has never been seriously tidied or+checked for robustness, but it shouldn't now give compiler warnings.++There is only one option: "-s". If given, it applies only to the "findprop" +command. It causes the UTF-8 sequence of bytes that encode the character to be +output between angle brackets at the end of the line. On a UTF-8 terminal, this +will show the appropriate graphic for the code point.++If the command has arguments, they are concatenated into a buffer, separated by+spaces. If the first argument starts "U+" or consists entirely of hexadecimal+digits, "findprop" is inserted at the start. The buffer is then processed as a+single line file, after which the program exits. If there are no arguments, the+program reads commands line by line on stdin and writes output to stdout. The +return code is always zero.++There are three commands:++"findprop" must be followed by a space-separated list of Unicode code points as+hex numbers, either without any prefix or starting with "U+". The output is one+line per character, giving its Unicode properties followed by its other case or +cases if one or more exist, followed by its Script Extension list if it is not+just the same as the base script. This list is in square brackets. The+properties are:++General type e.g. Letter+Specific type e.g. Upper case letter+Script e.g. Medefaidrin+Grapheme break type e.g. Extend (most common is Other)++"find" must be followed by a list of property names and their values. The +values are case-sensitive. This finds characters that have those properties. If+multiple properties are listed, they must all be matched. Currently supported:++ script <name> The character must have this script property. Only one+ such script may be given.+ scriptx <name> This script must be in the character's Script Extension+ property list. If this is used many times, all the given+ scripts must be present.+ type <abbrev> The character's specific type (e.g. Lu or Nd) must match.+ gbreak <name> The grapheme break property must match.++If a <name> or <abbrev> is preceded by !, the value must NOT be present. For+Script Extensions, there may be a mixture of positive and negative+requirements. All must be satisfied.++Sequences of two or more characters are shown as ranges, for example+U+0041..U+004A. No more than 100 lines are are output. If there are more+characters, the list ends with ... ++"list" must be followed by a property name (script, type, or gbreak). The+defined values for that property are listed. */+++#ifdef HAVE_CONFIG_H+#include "../src/config.h"+#endif++#ifndef SUPPORT_UNICODE+#define SUPPORT_UNICODE+#endif++#include <ctype.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include "../src/pcre2_internal.h"+#include "../src/pcre2_ucp.h"++#ifdef HAVE_UNISTD_H+#include <unistd.h>+#endif++#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+#if defined(SUPPORT_LIBREADLINE)+#include <readline/readline.h>+#include <readline/history.h>+#else+#if defined(HAVE_EDITLINE_READLINE_H)+#include <editline/readline.h>+#else+#include <readline/readline.h>+#endif+#endif+#endif+++/* -------------------------------------------------------------------*/++#define CS (char *)+#define CCS (const char *)+#define CSS (char **)+#define US (unsigned char *)+#define CUS (const unsigned char *)+#define USS (unsigned char **)++/* -------------------------------------------------------------------*/++static BOOL show_character = FALSE;++static const unsigned char *type_names[] = {+ US"Cc", US"Control",+ US"Cf", US"Format",+ US"Cn", US"Unassigned",+ US"Co", US"Private use",+ US"Cs", US"Surrogate",+ US"Ll", US"Lower case letter",+ US"Lm", US"Modifier letter",+ US"Lo", US"Other letter",+ US"Lt", US"Title case letter",+ US"Lu", US"Upper case letter",+ US"Mc", US"Spacing mark",+ US"Me", US"Enclosing mark",+ US"Mn", US"Non-spacing mark",+ US"Nd", US"Decimal number",+ US"Nl", US"Letter number",+ US"No", US"Other number",+ US"Pc", US"Connector punctuation",+ US"Pd", US"Dash punctuation",+ US"Pe", US"Close punctuation",+ US"Pf", US"Final punctuation",+ US"Pi", US"Initial punctuation",+ US"Po", US"Other punctuation",+ US"Ps", US"Open punctuation",+ US"Sc", US"Currency symbol",+ US"Sk", US"Modifier symbol",+ US"Sm", US"Mathematical symbol",+ US"So", US"Other symbol",+ US"Zl", US"Line separator",+ US"Zp", US"Paragraph separator",+ US"Zs", US"Space separator" +};++static const unsigned char *gb_names[] = {+ US"CR", US"carriage return",+ US"LF", US"linefeed",+ US"Control", US"",+ US"Extend", US"",+ US"Prepend", US"",+ US"SpacingMark", US"",+ US"L", US"Hangul syllable type L",+ US"V", US"Hangul syllable type V",+ US"T", US"Hangul syllable type T",+ US"LV", US"Hangul syllable type LV",+ US"LVT", US"Hangul syllable type LVT",+ US"RegionalIndicator", US"",+ US"Other", US"",+ US"ZWJ", US"zero width joiner",+ US"Extended_Pictographic", US""+};+++static const unsigned int utf8_table1[] = {+ 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff};++static const int utf8_table2[] = {+ 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};+++/*************************************************+* Convert character value to UTF-8 *+*************************************************/++/* This function takes an unsigned long integer value in the range 0 -+0x7fffffff and encodes it as a UTF-8 character in 1 to 6 bytes.++Arguments:+ cvalue the character value+ buffer pointer to buffer for result - at least 6 bytes long++Returns: number of bytes placed in the buffer+ 0 if input code point is too big+*/++static size_t+ord2utf8(unsigned int cvalue, unsigned char *buffer)+{+size_t i, j;+for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)+ if (cvalue <= utf8_table1[i]) break;+if (i >= sizeof(utf8_table1)/sizeof(int)) return 0;+buffer += i;+for (j = i; j > 0; j--)+ {+ *buffer-- = 0x80 | (cvalue & 0x3f);+ cvalue >>= 6;+ }+*buffer = utf8_table2[i] | cvalue;+return i + 1;+}++++/*************************************************+* Test for interaction *+*************************************************/++static BOOL+is_stdin_tty(void)+{+#if defined WIN32+return _isatty(_fileno(stdin));+#else+return isatty(fileno(stdin));+#endif+}+++/*************************************************+* Get script name from ucp ident *+*************************************************/++static const char *+get_scriptname(int script)+{+size_t i;+const ucp_type_table *u;++for (i = 0; i < PRIV(utt_size); i++)+ {+ u = PRIV(utt) + i; + if (u->type == PT_SC && u->value == script) break;+ }+if (i < PRIV(utt_size))+ return PRIV(utt_names) + u->name_offset;+ +return "??";+} +++/*************************************************+* Print Unicode property info for a char *+*************************************************/++static void+print_prop(unsigned int c, BOOL is_just_one)+{+int type = UCD_CATEGORY(c);+int fulltype = UCD_CHARTYPE(c);+int script = UCD_SCRIPT(c);+int scriptx = UCD_SCRIPTX(c);+int gbprop = UCD_GRAPHBREAK(c);+unsigned int othercase = UCD_OTHERCASE(c);+int caseset = UCD_CASESET(c);++const unsigned char *fulltypename = US"??";+const unsigned char *typename = US"??";+const unsigned char *graphbreak = US"??";+const unsigned char *scriptname = CUS get_scriptname(script);++switch (type)+ {+ case ucp_C: typename = US"Control"; break;+ case ucp_L: typename = US"Letter"; break;+ case ucp_M: typename = US"Mark"; break;+ case ucp_N: typename = US"Number"; break;+ case ucp_P: typename = US"Punctuation"; break;+ case ucp_S: typename = US"Symbol"; break;+ case ucp_Z: typename = US"Separator"; break;+ }++switch (fulltype)+ {+ case ucp_Cc: fulltypename = US"Control"; break;+ case ucp_Cf: fulltypename = US"Format"; break;+ case ucp_Cn: fulltypename = US"Unassigned"; break;+ case ucp_Co: fulltypename = US"Private use"; break;+ case ucp_Cs: fulltypename = US"Surrogate"; break;+ case ucp_Ll: fulltypename = US"Lower case letter"; break;+ case ucp_Lm: fulltypename = US"Modifier letter"; break;+ case ucp_Lo: fulltypename = US"Other letter"; break;+ case ucp_Lt: fulltypename = US"Title case letter"; break;+ case ucp_Lu: fulltypename = US"Upper case letter"; break;+ case ucp_Mc: fulltypename = US"Spacing mark"; break;+ case ucp_Me: fulltypename = US"Enclosing mark"; break;+ case ucp_Mn: fulltypename = US"Non-spacing mark"; break;+ case ucp_Nd: fulltypename = US"Decimal number"; break;+ case ucp_Nl: fulltypename = US"Letter number"; break;+ case ucp_No: fulltypename = US"Other number"; break;+ case ucp_Pc: fulltypename = US"Connector punctuation"; break;+ case ucp_Pd: fulltypename = US"Dash punctuation"; break;+ case ucp_Pe: fulltypename = US"Close punctuation"; break;+ case ucp_Pf: fulltypename = US"Final punctuation"; break;+ case ucp_Pi: fulltypename = US"Initial punctuation"; break;+ case ucp_Po: fulltypename = US"Other punctuation"; break;+ case ucp_Ps: fulltypename = US"Open punctuation"; break;+ case ucp_Sc: fulltypename = US"Currency symbol"; break;+ case ucp_Sk: fulltypename = US"Modifier symbol"; break;+ case ucp_Sm: fulltypename = US"Mathematical symbol"; break;+ case ucp_So: fulltypename = US"Other symbol"; break;+ case ucp_Zl: fulltypename = US"Line separator"; break;+ case ucp_Zp: fulltypename = US"Paragraph separator"; break;+ case ucp_Zs: fulltypename = US"Space separator"; break;+ }++switch(gbprop)+ {+ case ucp_gbCR: graphbreak = US"CR"; break;+ case ucp_gbLF: graphbreak = US"LF"; break;+ case ucp_gbControl: graphbreak = US"Control"; break;+ case ucp_gbExtend: graphbreak = US"Extend"; break;+ case ucp_gbPrepend: graphbreak = US"Prepend"; break;+ case ucp_gbSpacingMark: graphbreak = US"SpacingMark"; break;+ case ucp_gbL: graphbreak = US"Hangul syllable type L"; break;+ case ucp_gbV: graphbreak = US"Hangul syllable type V"; break;+ case ucp_gbT: graphbreak = US"Hangul syllable type T"; break;+ case ucp_gbLV: graphbreak = US"Hangul syllable type LV"; break;+ case ucp_gbLVT: graphbreak = US"Hangul syllable type LVT"; break;+ case ucp_gbRegionalIndicator:+ graphbreak = US"Regional Indicator"; break;+ case ucp_gbOther: graphbreak = US"Other"; break;+ case ucp_gbZWJ: graphbreak = US"Zero Width Joiner"; break;+ case ucp_gbExtended_Pictographic:+ graphbreak = US"Extended Pictographic"; break;+ default: graphbreak = US"Unknown"; break;+ }++printf("U+%04X %s: %s, %s, %s", c, typename, fulltypename, scriptname, graphbreak);+if (is_just_one && othercase != c)+ {+ printf(", U+%04X", othercase);+ if (caseset != 0)+ {+ const uint32_t *p = PRIV(ucd_caseless_sets) + caseset - 1;+ while (*(++p) < NOTACHAR)+ {+ unsigned int d = *p; + if (d != othercase && d != c) printf(", U+%04X", d);+ } + }+ }++if (scriptx != script)+ {+ printf(", [");+ if (scriptx >= 0)+ printf("%s", get_scriptname(scriptx));+ else+ {+ const char *sep = "";+ const uint8_t *p = PRIV(ucd_script_sets) - scriptx;+ while (*p != 0)+ {+ printf("%s%s", sep, get_scriptname(*p++));+ sep = ", ";+ }+ }+ printf("]");+ }+ +if (show_character && is_just_one)+ {+ unsigned char buffer[8];+ size_t len = ord2utf8(c, buffer);+ printf(", >%.*s<", (int)len, buffer); + } ++printf("\n");+}++++/*************************************************+* Find character(s) with given property/ies *+*************************************************/++static void+find_chars(unsigned char *s)+{+unsigned char name[24];+unsigned char value[24];+unsigned char *t;+unsigned int count= 0;+int scriptx_list[24];+unsigned int scriptx_count = 0;+uint32_t i, c;+int script = -1;+int type = -1;+int gbreak = -1;+BOOL script_not = FALSE;+BOOL type_not = FALSE;+BOOL gbreak_not = FALSE;+BOOL hadrange = FALSE;+const ucd_record *ucd, *next_ucd;+const char *pad = " ";++while (*s != 0)+ {+ unsigned int offset = 0;+ BOOL scriptx_not = FALSE;++ for (t = name; *s != 0 && !isspace(*s); s++) *t++ = *s;+ *t = 0;+ while (isspace(*s)) s++;++ for (t = value; *s != 0 && !isspace(*s); s++) *t++ = *s;+ *t = 0;+ while (isspace(*s)) s++;++ if (strcmp(CS name, "script") == 0 ||+ strcmp(CS name, "scriptx") == 0)+ {+ if (value[0] == '!')+ {+ if (name[6] == 'x') scriptx_not = TRUE;+ else script_not = TRUE;+ offset = 1;+ }++ for (i = 0; i < PRIV(utt_size); i++)+ {+ const ucp_type_table *u = PRIV(utt) + i; + if (u->type == PT_SC && strcmp(CS(value + offset), + PRIV(utt_names) + u->name_offset) == 0)+ {+ c = u->value; + if (name[6] == 'x')+ {+ scriptx_list[scriptx_count++] = scriptx_not? (-c):c;+ }+ else+ {+ if (script < 0) script = c; else+ {+ printf("** Only 1 script value allowed\n");+ return;+ }+ }+ break;+ }+ }++ if (i >= PRIV(utt_size))+ {+ printf("** Unrecognized script name \"%s\"\n", value);+ return;+ }+ }++ else if (strcmp(CS name, "type") == 0)+ {+ if (type >= 0)+ {+ printf("** Only 1 type value allowed\n");+ return;+ }+ else+ {+ if (value[0] == '!')+ {+ type_not = TRUE;+ offset = 1;+ }++ for (i = 0; i < sizeof(type_names)/sizeof(char *); i += 2)+ {+ if (strcmp(CS (value + offset), CS type_names[i]) == 0)+ {+ type = i/2;+ break;+ }+ }+ if (i >= sizeof(type_names)/sizeof(char *))+ {+ printf("** Unrecognized type name \"%s\"\n", value);+ return;+ }+ }+ }++ else if (strcmp(CS name, "gbreak") == 0)+ {+ if (gbreak >= 0)+ {+ printf("** Only 1 grapheme break value allowed\n");+ return;+ }+ else+ {+ if (value[0] == '!')+ {+ gbreak_not = TRUE;+ offset = 1;+ }++ for (i = 0; i < sizeof(gb_names)/sizeof(char *); i += 2)+ {+ if (strcmp(CS (value + offset), CS gb_names[i]) == 0)+ {+ gbreak = i/2;+ break;+ }+ }+ if (i >= sizeof(gb_names)/sizeof(char *))+ {+ printf("** Unrecognized gbreak name \"%s\"\n", value);+ return;+ }+ }+ }++ else+ {+ printf("** Unrecognized property name \"%s\"\n", name);+ return;+ }+ }++if (script < 0 && scriptx_count == 0 && type < 0 && gbreak < 0)+ {+ printf("** No properties specified\n");+ return;+ }++for (c = 0; c <= 0x10ffff; c++)+ {+ if (script >= 0 && (script == UCD_SCRIPT(c)) == script_not) continue;++ if (scriptx_count > 0)+ {+ const uint8_t *char_scriptx = NULL;+ unsigned int found = 0;+ int scriptx = UCD_SCRIPTX(c);++ if (scriptx < 0) char_scriptx = PRIV(ucd_script_sets) - scriptx;++ for (i = 0; i < scriptx_count; i++)+ {+ /* Positive requirment */+ if (scriptx_list[i] >= 0)+ {+ if (scriptx >= 0)+ {+ if (scriptx == scriptx_list[i]) found++;+ }++ else+ {+ const uint8_t *p;+ for (p = char_scriptx; *p != 0; p++)+ {+ if (scriptx_list[i] == *p)+ {+ found++;+ break;+ }+ }+ }+ }+ /* Negative requirement */+ else+ {+ if (scriptx >= 0)+ {+ if (scriptx != -scriptx_list[i]) found++;+ }+ else+ {+ const uint8_t *p;+ for (p = char_scriptx; *p != 0; p++)+ if (-scriptx_list[i] == *p) break;+ if (*p == 0) found++;+ }+ }+ }++ if (found != scriptx_count) continue;+ }++ if (type >= 0)+ {+ if (type_not)+ {+ if (type == UCD_CHARTYPE(c)) continue;+ }+ else+ {+ if (type != UCD_CHARTYPE(c)) continue;+ }+ }++ if (gbreak >= 0)+ {+ if (gbreak_not)+ {+ if (gbreak == UCD_GRAPHBREAK(c)) continue;+ }+ else+ {+ if (gbreak != UCD_GRAPHBREAK(c)) continue;+ }+ }++ /* All conditions are met. Look for runs. */++ ucd = GET_UCD(c);++ for (i = c + 1; i < 0x10ffff; i++)+ {+ next_ucd = GET_UCD(i);+ if (memcmp(ucd, next_ucd, sizeof(ucd_record)) != 0) break;+ }++ if (--i > c)+ {+ printf("U+%04X..", c);+ c = i;+ hadrange = TRUE;+ }+ else if (hadrange) printf("%s", pad);++ print_prop(c, FALSE);+ if (c >= 0x100000) pad = " ";+ else if (c >= 0x10000) pad = " ";+ count++;+ if (count >= 100)+ {+ printf("...\n");+ break;+ }+ }++if (count == 0) printf("No characters found\n");+}+++/*************************************************+* Process command line *+*************************************************/++static void+process_command_line(unsigned char *buffer)+{+unsigned char *s, *t;+unsigned char name[24];++s = buffer;+while (isspace(*s)) s++;+if (*s == 0) return;++for (t = name; *s != 0 && !isspace(*s); s++) *t++ = *s;+*t = 0;+while (isspace(*s)) s++;++if (strcmp(CS name, "findprop") == 0)+ {+ while (*s != 0)+ {+ unsigned int c; + unsigned char *endptr;+ t = s; + if (strncmp(CS t, "U+", 2) == 0) t += 2;+ c = strtoul(CS t, CSS(&endptr), 16);+ if (*endptr != 0 && !isspace(*endptr))+ {+ while (*endptr != 0 && !isspace(*endptr)) endptr++;+ printf("** Invalid hex number: ignored \"%.*s\"\n", (int)(endptr-s), s);+ }+ else + {+ if (c > 0x10ffff) + printf("** U+%x is too big for a Unicode code point\n", c);+ else + print_prop(c, TRUE);+ } + s = endptr;+ while (isspace(*s)) s++;+ }+ }++else if (strcmp(CS name, "find") == 0)+ {+ find_chars(s);+ }+ +else if (strcmp(CS name, "list") == 0)+ {+ while (*s != 0)+ {+ size_t i;+ for (t = name; *s != 0 && !isspace(*s); s++) *t++ = *s;+ *t = 0;+ while (isspace(*s)) s++;+ + if (strcmp(CS name, "script") == 0 || strcmp(CS name, "scripts") == 0)+ {+ for (i = 0; i < PRIV(utt_size); i++) + if (PRIV(utt)[i].type == PT_SC)+ printf("%s\n", PRIV(utt_names) + PRIV(utt)[i].name_offset); + }+ + else if (strcmp(CS name, "type") == 0 || strcmp(CS name, "types") == 0)+ {+ for (i = 0; i < sizeof(type_names)/sizeof(char *); i += 2)+ printf("%s %s\n", type_names[i], type_names[i+1]); + } + + else if (strcmp(CS name, "gbreak") == 0 || strcmp(CS name, "gbreaks") == 0)+ {+ for (i = 0; i < sizeof(gb_names)/sizeof(char *); i += 2)+ {+ if (gb_names[i+1][0] != 0) + printf("%-3s (%s)\n", gb_names[i], gb_names[i+1]);+ else + printf("%s\n", gb_names[i]);+ } + } ++ else + {+ printf("** Unknown property \"%s\"\n", name); + break;+ } + } + } ++else printf("** Unknown test command \"%s\"\n", name);+}++++/*************************************************+* Main program *+*************************************************/++int+main(int argc, char **argv)+{+BOOL interactive;+int first_arg = 1;+unsigned char buffer[1024];++if (argc > 1 && strcmp(argv[1], "-s") == 0)+ {+ show_character = TRUE;+ first_arg++;+ } ++if (argc > first_arg)+ {+ int i;+ BOOL hexfirst = TRUE; + char *arg = argv[first_arg]; + unsigned char *s = buffer;+ + if (strncmp(arg, "U+", 2) != 0 && !isdigit(*arg)) + {+ while (*arg != 0) + {+ if (!isxdigit(*arg++)) { hexfirst = FALSE; break; } + } + } + + if (hexfirst)+ {+ strcpy(CS s, "findprop ");+ s += 9;+ }+ + for (i = first_arg; i < argc; i++)+ {+ s += sprintf(CS s, "%s ", argv[i]); + }++ process_command_line(buffer);+ return 0;+ }++interactive = is_stdin_tty();++#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+if (interactive) using_history();+#endif++for(;;)+ {+#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+ if (interactive)+ {+ size_t len;+ unsigned char *s = US readline("> ");+ if (s == NULL) break;+ len = strlen(CS s);+ if (len > 0) add_history(CS s);+ memcpy(buffer, s, len);+ buffer[len] = '\n';+ buffer[len+1] = 0;+ free(s);+ }+ else+#endif++ {+ if (interactive) printf("> ");+ if (fgets(CS buffer, sizeof(buffer), stdin) == NULL) break;+ if (!interactive) printf("%s", buffer);+ }+ + process_command_line(buffer);+ }++if (interactive) printf("\n");++#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+if (interactive) clear_history();+#endif++return 0;+}++/* End */
+ src/c/pcre2/maint/utf8.c view
@@ -0,0 +1,347 @@+/****************************************************+* PCRE maintainers' helper program: UTF-8 converter *+****************************************************/++/* This is a test program for converting character code points to UTF-8 and+vice versa. Note that this program conforms to the original definition of+UTF-8, which allows codepoints up to 7fffffff. The more recent definition+limits the validity of Unicode UTF-8 codepoints to a maximum of 10ffffff, and+forbids the "surrogate" code points. This program now gives warnings for these+invalid code points.++The arguments are either single code point values written as U+hh.. or 0xhh..+for conversion to UTF-8, or sequences of hex values, written without 0x and+optionally including spaces (but such arguments must be quoted), for conversion+from UTF-8 to codepoints. For example:++./utf8 0x1234+U+00001234 => e1 88 b4++./utf8 "e1 88 b4"+U+00001234 <= e1 88 b4++In the second case, a number of UTF-8 characters can be present in one+argument. In other words, each such argument is interpreted (after ignoring+spaces) as a string of UTF-8 bytes representing a string of characters:++./utf8 "65 e188b4 77"+0x00000065 <= 65+0x00001234 <= e1 88 b4+0x00000077 <= 77++If the option -s is given, the sequence of UTF-bytes is written out between+angle brackets at the end of the line. On a UTF-8 terminal, this will show the+appropriate graphic for the code point.++Errors provoke error messages, but the program carries on with the next+argument. The return code is always zero.++Philip Hazel+Original creation data: unknown+Code extended and tidied to avoid compiler warnings: 26 March 2020+*/+++#include <stdio.h>+#include <stdlib.h>+#include <ctype.h>+#include <string.h>++/* The valid ranges for UTF-8 characters are:++0000 0000 to 0000 007f 1 byte (ascii)+0000 0080 to 0000 07ff 2 bytes+0000 0800 to 0000 ffff 3 bytes+0001 0000 to 001f ffff 4 bytes+0020 0000 to 03ff ffff 5 bytes+0400 0000 to 7fff ffff 6 bytes+*/+++static const unsigned int utf8_table1[] = {+ 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff};++static const int utf8_table2[] = {+ 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};++static const int utf8_table3[] = {+ 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};+++/*************************************************+* Convert character value to UTF-8 *+*************************************************/++/* This function takes an unsigned long integer value in the range 0 -+0x7fffffff and encodes it as a UTF-8 character in 1 to 6 bytes.++Arguments:+ cvalue the character value+ buffer pointer to buffer for result - at least 6 bytes long++Returns: number of bytes placed in the buffer+ 0 if input code point is too big+*/++static size_t+ord2utf8(unsigned long int cvalue, unsigned char *buffer)+{+size_t i, j;+for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)+ if (cvalue <= utf8_table1[i]) break;+if (i >= sizeof(utf8_table1)/sizeof(int)) return 0;+buffer += i;+for (j = i; j > 0; j--)+ {+ *buffer-- = 0x80 | (cvalue & 0x3f);+ cvalue >>= 6;+ }+*buffer = utf8_table2[i] | cvalue;+return i + 1;+}++++/*************************************************+* Convert UTF-8 string to value *+*************************************************/++/* This function takes one or more bytes that represent a UTF-8 character from+the start of a string of bytes. It returns the value of the character, or the+offset of a malformation. For an overlong encoding that works but is not the+correct (shortest) one, the error offset is just after the last byte.++Argument:+ buffer a pointer to the byte vector+ buffend a pointer to the end of the buffer+ vptr a pointer to a variable to receive the value+ lenptr a pointer to a variable to receive the offset when error detected++Returns: > 0 => the number of bytes consumed+ 0 => invalid UTF-8: first byte missing 0x40 bit+ -1 => invalid UTF-8: first byte has too many high-order 1-bits+ -2 => incomplete sequence at end of string+ -3 => incomplete sequence within string+ -4 => overlong code sequence+*/++static int+utf82ord(unsigned char *buffer, unsigned char *buffend,+ long unsigned int *vptr, int *lenptr)+{+unsigned int c = *buffer++;+unsigned int d = c;+int i, j, s;++/* Check for an ASCII character, or find the number of additional bytes in a+multibyte character. */++for (i = -1; i < 6; i++)+ {+ if ((d & 0x80) == 0) break;+ d <<= 1;+ }++switch (i)+ {+ case -1: /* ASCII character; first byte does not have 0x80 bit */+ *vptr = c;+ return 1;++ case 0: /* First byte has 0x80 but is missing 0x40 bit */+ *lenptr = 0;+ return 0;++ case 6:+ *lenptr = 0; /* Too many high bits */+ return -1;++ default:+ break;+ }++/* i now has a value in the range 1-5 */++s = 6*i;+d = (c & utf8_table3[i]) << s;++for (j = 0; j < i; j++)+ {+ if (buffer >= buffend)+ {+ *lenptr = j + 1;+ return -2;+ }+ c = *buffer++;+ if ((c & 0xc0) != 0x80)+ {+ *lenptr = j + 1;+ return -3;+ }+ s -= 6;+ d |= (c & 0x3f) << s;+ }++/* Valid UTF-8 syntax */++*vptr = d;++/* Check that encoding was the correct one, not overlong */++for (j = 0; j < (int)(sizeof(utf8_table1)/sizeof(int)); j++)+ if (d <= utf8_table1[j]) break;+if (j != i)+ {+ *lenptr = i + 1;+ return -4;+ }++/* Valid value */++return i + 1;+}++++/*************************************************+* Main Program *+*************************************************/++int+main(int argc, char **argv)+{+int i = 1;+int show = 0;+unsigned char buffer[64];++if (argc > 1 && strcmp(argv[1], "-s") == 0)+ {+ show = 1;+ i = 2;+ }++for (; i < argc; i++)+ {+ char *x = argv[i];+ char *endptr;+ if (strncmp(x, "0x", 2) == 0 || strncmp(x, "U+", 2) == 0)+ {+ size_t rc, j;+ unsigned long int d = strtoul(x+2, &endptr, 16);+ if (*endptr != 0)+ {+ printf("** Invalid hex number %s\n", x);+ continue; /* With next argument */+ }+ rc = ord2utf8(d, buffer);+ printf("U+%08lx => ", d);+ if (rc == 0)+ printf("** Code point greater than 0x7fffffff cannot be encoded");+ else+ {+ for (j = 0; j < rc; j++) printf("%02x ", buffer[j]);+ if (show)+ {+ printf(">");+ for (j = 0; j < rc; j++) printf("%c", buffer[j]);+ printf("< ");+ }+ if (d >= 0xd800 && d <= 0xdfff)+ printf("** Invalid Unicode (surrogate)");+ else if (d > 0x10ffff)+ printf("** Invalid Unicode (greater than U+10ffff)");+ }+ printf("\n");+ }+ else+ {+ unsigned char *bptr;+ unsigned char *buffend;+ int len = 0;+ int y = 0;+ int z = 0;++ for (;;)+ {+ while (*x == ' ') x++;+ if (*x == 0 && !z) break;+ if (!isxdigit(*x))+ {+ printf("** Malformed hex string: %s\n", argv[i]);+ len = -1;+ break;+ }+ y = y * 16 + tolower(*x) - ((isdigit(*x))? '0' : 'W');+ x++;+ if (z)+ {+ buffer[len++] = y;+ y = 0;+ }+ z ^= 1;+ }++ if (len < 0) continue; /* With next argument after malformation */++ bptr = buffer;+ buffend = buffer + len;++ while (bptr < buffend)+ {+ unsigned long int d;+ int j;+ int offset;+ int rc = utf82ord(bptr, buffend, &d, &offset);++ if (rc > 0)+ {+ printf("U+%08lx <= ", d);+ for (j = 0; j < rc; j++) printf("%02x ", bptr[j]);+ if (show)+ {+ printf(">");+ for (j = 0; j < rc; j++) printf("%c", bptr[j]);+ printf("<");+ }+ printf("\n");+ bptr += rc;+ }+ else if (rc == -4)+ {+ printf("U+%08lx <= ", d);+ for (j = 0; j < offset; j++) printf("%02x ", bptr[j]);+ printf("** Overlong UTF-8 sequence\n");+ bptr += offset;+ }+ else+ {+ switch (rc)+ {+ case 0: printf("** First byte missing 0x40 bit");+ break;++ case -1: printf("** First byte has too many high-order bits");+ break;++ case -2: printf("** Incomplete UTF-8 sequence at end of string");+ break;++ case -3: printf("** Incomplete UTF-8 sequence");+ break;++ default: printf("** Unexpected return %d from utf82ord()", rc);+ break;+ }+ printf(" at offset %d in string ", offset);+ while (bptr < buffend) printf("%02x ", *bptr++);+ printf("\n");+ break;+ }+ }+ }+ }++return 0;+}++/* End */
+ src/c/pcre2/src/pcre2_auto_possess.c view
@@ -0,0 +1,1343 @@+/*************************************************+* 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) 2016-2020 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.+-----------------------------------------------------------------------------+*/++/* This module contains functions that scan a compiled pattern and change+repeats into possessive repeats where possible. */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif+++#include "pcre2_internal.h"+++/*************************************************+* Tables for auto-possessification *+*************************************************/++/* This table is used to check whether auto-possessification is possible+between adjacent character-type opcodes. The left-hand (repeated) opcode is+used to select the row, and the right-hand opcode is use to select the column.+A value of 1 means that auto-possessification is OK. For example, the second+value in the first row means that \D+\d can be turned into \D++\d.++The Unicode property types (\P and \p) have to be present to fill out the table+because of what their opcode values are, but the table values should always be+zero because property types are handled separately in the code. The last four+columns apply to items that cannot be repeated, so there is no need to have+rows for them. Note that OP_DIGIT etc. are generated only when PCRE_UCP is+*not* set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */++#define APTROWS (LAST_AUTOTAB_LEFT_OP - FIRST_AUTOTAB_OP + 1)+#define APTCOLS (LAST_AUTOTAB_RIGHT_OP - FIRST_AUTOTAB_OP + 1)++static const uint8_t autoposstab[APTROWS][APTCOLS] = {+/* \D \d \S \s \W \w . .+ \C \P \p \R \H \h \V \v \X \Z \z $ $M */+ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \D */+ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \d */+ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \S */+ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \s */+ { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \W */+ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \w */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* . */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* .+ */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \C */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* \P */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* \p */+ { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, /* \R */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, /* \H */+ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0 }, /* \h */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0 }, /* \V */+ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, /* \v */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } /* \X */+};++#ifdef SUPPORT_UNICODE+/* This table is used to check whether auto-possessification is possible+between adjacent Unicode property opcodes (OP_PROP and OP_NOTPROP). The+left-hand (repeated) opcode is used to select the row, and the right-hand+opcode is used to select the column. The values are as follows:++ 0 Always return FALSE (never auto-possessify)+ 1 Character groups are distinct (possessify if both are OP_PROP)+ 2 Check character categories in the same group (general or particular)+ 3 TRUE if the two opcodes are not the same (PROP vs NOTPROP)++ 4 Check left general category vs right particular category+ 5 Check right general category vs left particular category++ 6 Left alphanum vs right general category+ 7 Left space vs right general category+ 8 Left word vs right general category++ 9 Right alphanum vs left general category+ 10 Right space vs left general category+ 11 Right word vs left general category++ 12 Left alphanum vs right particular category+ 13 Left space vs right particular category+ 14 Left word vs right particular category++ 15 Right alphanum vs left particular category+ 16 Right space vs left particular category+ 17 Right word vs left particular category+*/++static const uint8_t propposstab[PT_TABSIZE][PT_TABSIZE] = {+/* ANY LAMP GC PC SC ALNUM SPACE PXSPACE WORD CLIST UCNC */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_ANY */+ { 0, 3, 0, 0, 0, 3, 1, 1, 0, 0, 0 }, /* PT_LAMP */+ { 0, 0, 2, 4, 0, 9, 10, 10, 11, 0, 0 }, /* PT_GC */+ { 0, 0, 5, 2, 0, 15, 16, 16, 17, 0, 0 }, /* PT_PC */+ { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, /* PT_SC */+ { 0, 3, 6, 12, 0, 3, 1, 1, 0, 0, 0 }, /* PT_ALNUM */+ { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_SPACE */+ { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_PXSPACE */+ { 0, 0, 8, 14, 0, 0, 1, 1, 3, 0, 0 }, /* PT_WORD */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 } /* PT_UCNC */+};++/* This table is used to check whether auto-possessification is possible+between adjacent Unicode property opcodes (OP_PROP and OP_NOTPROP) when one+specifies a general category and the other specifies a particular category. The+row is selected by the general category and the column by the particular+category. The value is 1 if the particular category is not part of the general+category. */++static const uint8_t catposstab[7][30] = {+/* Cc Cf Cn Co Cs Ll Lm Lo Lt Lu Mc Me Mn Nd Nl No Pc Pd Pe Pf Pi Po Ps Sc Sk Sm So Zl Zp Zs */+ { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* C */+ { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* L */+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* M */+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* N */+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 }, /* P */+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1 }, /* S */+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 } /* Z */+};++/* This table is used when checking ALNUM, (PX)SPACE, SPACE, and WORD against+a general or particular category. The properties in each row are those+that apply to the character set in question. Duplication means that a little+unnecessary work is done when checking, but this keeps things much simpler+because they can all use the same code. For more details see the comment where+this table is used.++Note: SPACE and PXSPACE used to be different because Perl excluded VT from+"space", but from Perl 5.18 it's included, so both categories are treated the+same here. */++static const uint8_t posspropstab[3][4] = {+ { ucp_L, ucp_N, ucp_N, ucp_Nl }, /* ALNUM, 3rd and 4th values redundant */+ { ucp_Z, ucp_Z, ucp_C, ucp_Cc }, /* SPACE and PXSPACE, 2nd value redundant */+ { ucp_L, ucp_N, ucp_P, ucp_Po } /* WORD */+};+#endif /* SUPPORT_UNICODE */++++#ifdef SUPPORT_UNICODE+/*************************************************+* Check a character and a property *+*************************************************/++/* This function is called by compare_opcodes() when a property item is+adjacent to a fixed character.++Arguments:+ c the character+ ptype the property type+ pdata the data for the type+ negated TRUE if it's a negated property (\P or \p{^)++Returns: TRUE if auto-possessifying is OK+*/++static BOOL+check_char_prop(uint32_t c, unsigned int ptype, unsigned int pdata,+ BOOL negated)+{+const uint32_t *p;+const ucd_record *prop = GET_UCD(c);++switch(ptype)+ {+ case PT_LAMP:+ return (prop->chartype == ucp_Lu ||+ prop->chartype == ucp_Ll ||+ prop->chartype == ucp_Lt) == negated;++ case PT_GC:+ return (pdata == PRIV(ucp_gentype)[prop->chartype]) == negated;++ case PT_PC:+ return (pdata == prop->chartype) == negated;++ case PT_SC:+ return (pdata == prop->script) == negated;++ /* These are specials */++ case PT_ALNUM:+ return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N) == negated;++ /* 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(c)+ {+ HSPACE_CASES:+ VSPACE_CASES:+ return negated;++ default:+ return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated;+ }+ break; /* Control never reaches here */++ case PT_WORD:+ return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||+ c == CHAR_UNDERSCORE) == negated;++ case PT_CLIST:+ p = PRIV(ucd_caseless_sets) + prop->caseset;+ for (;;)+ {+ if (c < *p) return !negated;+ if (c == *p++) return negated;+ }+ break; /* Control never reaches here */+ }++return FALSE;+}+#endif /* SUPPORT_UNICODE */++++/*************************************************+* Base opcode of repeated opcodes *+*************************************************/++/* Returns the base opcode for repeated single character type opcodes. If the+opcode is not a repeated character type, it returns with the original value.++Arguments: c opcode+Returns: base opcode for the type+*/++static PCRE2_UCHAR+get_repeat_base(PCRE2_UCHAR c)+{+return (c > OP_TYPEPOSUPTO)? c :+ (c >= OP_TYPESTAR)? OP_TYPESTAR :+ (c >= OP_NOTSTARI)? OP_NOTSTARI :+ (c >= OP_NOTSTAR)? OP_NOTSTAR :+ (c >= OP_STARI)? OP_STARI :+ OP_STAR;+}+++/*************************************************+* Fill the character property list *+*************************************************/++/* Checks whether the code points to an opcode that can take part in auto-+possessification, and if so, fills a list with its properties.++Arguments:+ code points to start of expression+ utf TRUE if in UTF mode+ ucp TRUE if in UCP mode+ fcc points to the case-flipping table+ list points to output list+ list[0] will be filled with the opcode+ list[1] will be non-zero if this opcode+ can match an empty character string+ list[2..7] depends on the opcode++Returns: points to the start of the next opcode if *code is accepted+ NULL if *code is not accepted+*/++static PCRE2_SPTR+get_chr_property_list(PCRE2_SPTR code, BOOL utf, BOOL ucp, const uint8_t *fcc,+ uint32_t *list)+{+PCRE2_UCHAR c = *code;+PCRE2_UCHAR base;+PCRE2_SPTR end;+uint32_t chr;++#ifdef SUPPORT_UNICODE+uint32_t *clist_dest;+const uint32_t *clist_src;+#else+(void)utf; /* Suppress "unused parameter" compiler warnings */+(void)ucp;+#endif++list[0] = c;+list[1] = FALSE;+code++;++if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)+ {+ base = get_repeat_base(c);+ c -= (base - OP_STAR);++ if (c == OP_UPTO || c == OP_MINUPTO || c == OP_EXACT || c == OP_POSUPTO)+ code += IMM2_SIZE;++ list[1] = (c != OP_PLUS && c != OP_MINPLUS && c != OP_EXACT &&+ c != OP_POSPLUS);++ switch(base)+ {+ case OP_STAR:+ list[0] = OP_CHAR;+ break;++ case OP_STARI:+ list[0] = OP_CHARI;+ break;++ case OP_NOTSTAR:+ list[0] = OP_NOT;+ break;++ case OP_NOTSTARI:+ list[0] = OP_NOTI;+ break;++ case OP_TYPESTAR:+ list[0] = *code;+ code++;+ break;+ }+ c = list[0];+ }++switch(c)+ {+ case OP_NOT_DIGIT:+ case OP_DIGIT:+ case OP_NOT_WHITESPACE:+ case OP_WHITESPACE:+ case OP_NOT_WORDCHAR:+ case OP_WORDCHAR:+ case OP_ANY:+ case OP_ALLANY:+ case OP_ANYNL:+ case OP_NOT_HSPACE:+ case OP_HSPACE:+ case OP_NOT_VSPACE:+ case OP_VSPACE:+ case OP_EXTUNI:+ case OP_EODN:+ case OP_EOD:+ case OP_DOLL:+ case OP_DOLLM:+ return code;++ case OP_CHAR:+ case OP_NOT:+ GETCHARINCTEST(chr, code);+ list[2] = chr;+ list[3] = NOTACHAR;+ return code;++ case OP_CHARI:+ case OP_NOTI:+ list[0] = (c == OP_CHARI) ? OP_CHAR : OP_NOT;+ GETCHARINCTEST(chr, code);+ list[2] = chr;++#ifdef SUPPORT_UNICODE+ if (chr < 128 || (chr < 256 && !utf && !ucp))+ list[3] = fcc[chr];+ else+ list[3] = UCD_OTHERCASE(chr);+#elif defined SUPPORT_WIDE_CHARS+ list[3] = (chr < 256) ? fcc[chr] : chr;+#else+ list[3] = fcc[chr];+#endif++ /* The othercase might be the same value. */++ if (chr == list[3])+ list[3] = NOTACHAR;+ else+ list[4] = NOTACHAR;+ return code;++#ifdef SUPPORT_UNICODE+ case OP_PROP:+ case OP_NOTPROP:+ if (code[0] != PT_CLIST)+ {+ list[2] = code[0];+ list[3] = code[1];+ return code + 2;+ }++ /* Convert only if we have enough space. */++ clist_src = PRIV(ucd_caseless_sets) + code[1];+ clist_dest = list + 2;+ code += 2;++ do {+ if (clist_dest >= list + 8)+ {+ /* Early return if there is not enough space. This should never+ happen, since all clists are shorter than 5 character now. */+ list[2] = code[0];+ list[3] = code[1];+ return code;+ }+ *clist_dest++ = *clist_src;+ }+ while(*clist_src++ != NOTACHAR);++ /* All characters are stored. The terminating NOTACHAR is copied from the+ clist itself. */++ list[0] = (c == OP_PROP) ? OP_CHAR : OP_NOT;+ return code;+#endif++ case OP_NCLASS:+ case OP_CLASS:+#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+ if (c == OP_XCLASS)+ end = code + GET(code, 0) - 1;+ else+#endif+ end = code + 32 / sizeof(PCRE2_UCHAR);++ switch(*end)+ {+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSSTAR:+ case OP_CRPOSQUERY:+ list[1] = TRUE;+ end++;+ break;++ case OP_CRPLUS:+ case OP_CRMINPLUS:+ case OP_CRPOSPLUS:+ end++;+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ list[1] = (GET2(end, 1) == 0);+ end += 1 + 2 * IMM2_SIZE;+ break;+ }+ list[2] = (uint32_t)(end - code);+ return end;+ }+return NULL; /* Opcode not accepted */+}++++/*************************************************+* Scan further character sets for match *+*************************************************/++/* Checks whether the base and the current opcode have a common character, in+which case the base cannot be possessified.++Arguments:+ code points to the byte code+ utf TRUE in UTF mode+ ucp TRUE in UCP mode+ cb compile data block+ base_list the data list of the base opcode+ base_end the end of the base opcode+ rec_limit points to recursion depth counter++Returns: TRUE if the auto-possessification is possible+*/++static BOOL+compare_opcodes(PCRE2_SPTR code, BOOL utf, BOOL ucp, const compile_block *cb,+ const uint32_t *base_list, PCRE2_SPTR base_end, int *rec_limit)+{+PCRE2_UCHAR c;+uint32_t list[8];+const uint32_t *chr_ptr;+const uint32_t *ochr_ptr;+const uint32_t *list_ptr;+PCRE2_SPTR next_code;+#ifdef SUPPORT_WIDE_CHARS+PCRE2_SPTR xclass_flags;+#endif+const uint8_t *class_bitset;+const uint8_t *set1, *set2, *set_end;+uint32_t chr;+BOOL accepted, invert_bits;+BOOL entered_a_group = FALSE;++if (--(*rec_limit) <= 0) return FALSE; /* Recursion has gone too deep */++/* Note: the base_list[1] contains whether the current opcode has a greedy+(represented by a non-zero value) quantifier. This is a different from+other character type lists, which store here that the character iterator+matches to an empty string (also represented by a non-zero value). */++for(;;)+ {+ /* All operations move the code pointer forward.+ Therefore infinite recursions are not possible. */++ c = *code;++ /* Skip over callouts */++ if (c == OP_CALLOUT)+ {+ code += PRIV(OP_lengths)[c];+ continue;+ }++ if (c == OP_CALLOUT_STR)+ {+ code += GET(code, 1 + 2*LINK_SIZE);+ continue;+ }++ /* At the end of a branch, skip to the end of the group. */++ if (c == OP_ALT)+ {+ do code += GET(code, 1); while (*code == OP_ALT);+ c = *code;+ }++ /* Inspect the next opcode. */++ switch(c)+ {+ /* We can always possessify a greedy iterator at the end of the pattern,+ which is reached after skipping over the final OP_KET. A non-greedy+ iterator must never be possessified. */++ case OP_END:+ return base_list[1] != 0;++ /* When an iterator is at the end of certain kinds of group we can inspect+ what follows the group by skipping over the closing ket. Note that this+ does not apply to OP_KETRMAX or OP_KETRMIN because what follows any given+ iteration is variable (could be another iteration or could be the next+ item). As these two opcodes are not listed in the next switch, they will+ end up as the next code to inspect, and return FALSE by virtue of being+ unsupported. */++ case OP_KET:+ case OP_KETRPOS:+ /* The non-greedy case cannot be converted to a possessive form. */++ if (base_list[1] == 0) return FALSE;++ /* If the bracket is capturing it might be referenced by an OP_RECURSE+ so its last iterator can never be possessified if the pattern contains+ recursions. (This could be improved by keeping a list of group numbers that+ are called by recursion.) */++ switch(*(code - GET(code, 1)))+ {+ case OP_CBRA:+ case OP_SCBRA:+ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ if (cb->had_recurse) return FALSE;+ break;++ /* A script run might have to backtrack if the iterated item can match+ characters from more than one script. So give up unless repeating an+ explicit character. */++ case OP_SCRIPT_RUN:+ if (base_list[0] != OP_CHAR && base_list[0] != OP_CHARI)+ return FALSE;+ break;++ /* Atomic sub-patterns and assertions can always auto-possessify their+ last iterator. However, if the group was entered as a result of checking+ a previous iterator, this is not possible. */++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ONCE:+ return !entered_a_group;++ /* Non-atomic assertions - don't possessify last iterator. This needs+ more thought. */++ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ return FALSE;+ }++ /* Skip over the bracket and inspect what comes next. */++ code += PRIV(OP_lengths)[c];+ continue;++ /* Handle cases where the next item is a group. */++ case OP_ONCE:+ case OP_BRA:+ case OP_CBRA:+ next_code = code + GET(code, 1);+ code += PRIV(OP_lengths)[c];++ /* Check each branch. We have to recurse a level for all but the last+ branch. */++ while (*next_code == OP_ALT)+ {+ if (!compare_opcodes(code, utf, ucp, cb, base_list, base_end, rec_limit))+ return FALSE;+ code = next_code + 1 + LINK_SIZE;+ next_code += GET(next_code, 1);+ }++ entered_a_group = TRUE;+ continue;++ case OP_BRAZERO:+ case OP_BRAMINZERO:++ next_code = code + 1;+ if (*next_code != OP_BRA && *next_code != OP_CBRA &&+ *next_code != OP_ONCE) return FALSE;++ do next_code += GET(next_code, 1); while (*next_code == OP_ALT);++ /* The bracket content will be checked by the OP_BRA/OP_CBRA case above. */++ next_code += 1 + LINK_SIZE;+ if (!compare_opcodes(next_code, utf, ucp, cb, base_list, base_end,+ rec_limit))+ return FALSE;++ code += PRIV(OP_lengths)[c];+ continue;++ /* The next opcode does not need special handling; fall through and use it+ to see if the base can be possessified. */++ default:+ break;+ }++ /* We now have the next appropriate opcode to compare with the base. Check+ for a supported opcode, and load its properties. */++ code = get_chr_property_list(code, utf, ucp, cb->fcc, list);+ if (code == NULL) return FALSE; /* Unsupported */++ /* If either opcode is a small character list, set pointers for comparing+ characters from that list with another list, or with a property. */++ if (base_list[0] == OP_CHAR)+ {+ chr_ptr = base_list + 2;+ list_ptr = list;+ }+ else if (list[0] == OP_CHAR)+ {+ chr_ptr = list + 2;+ list_ptr = base_list;+ }++ /* Character bitsets can also be compared to certain opcodes. */++ else if (base_list[0] == OP_CLASS || list[0] == OP_CLASS+#if PCRE2_CODE_UNIT_WIDTH == 8+ /* In 8 bit, non-UTF mode, OP_CLASS and OP_NCLASS are the same. */+ || (!utf && (base_list[0] == OP_NCLASS || list[0] == OP_NCLASS))+#endif+ )+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (base_list[0] == OP_CLASS || (!utf && base_list[0] == OP_NCLASS))+#else+ if (base_list[0] == OP_CLASS)+#endif+ {+ set1 = (uint8_t *)(base_end - base_list[2]);+ list_ptr = list;+ }+ else+ {+ set1 = (uint8_t *)(code - list[2]);+ list_ptr = base_list;+ }++ invert_bits = FALSE;+ switch(list_ptr[0])+ {+ case OP_CLASS:+ case OP_NCLASS:+ set2 = (uint8_t *)+ ((list_ptr == list ? code : base_end) - list_ptr[2]);+ break;++#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+ xclass_flags = (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE;+ if ((*xclass_flags & XCL_HASPROP) != 0) return FALSE;+ if ((*xclass_flags & XCL_MAP) == 0)+ {+ /* No bits are set for characters < 256. */+ if (list[1] == 0) return (*xclass_flags & XCL_NOT) == 0;+ /* Might be an empty repeat. */+ continue;+ }+ set2 = (uint8_t *)(xclass_flags + 1);+ break;+#endif++ case OP_NOT_DIGIT:+ invert_bits = TRUE;+ /* Fall through */+ case OP_DIGIT:+ set2 = (uint8_t *)(cb->cbits + cbit_digit);+ break;++ case OP_NOT_WHITESPACE:+ invert_bits = TRUE;+ /* Fall through */+ case OP_WHITESPACE:+ set2 = (uint8_t *)(cb->cbits + cbit_space);+ break;++ case OP_NOT_WORDCHAR:+ invert_bits = TRUE;+ /* Fall through */+ case OP_WORDCHAR:+ set2 = (uint8_t *)(cb->cbits + cbit_word);+ break;++ default:+ return FALSE;+ }++ /* Because the bit sets are unaligned bytes, we need to perform byte+ comparison here. */++ set_end = set1 + 32;+ if (invert_bits)+ {+ do+ {+ if ((*set1++ & ~(*set2++)) != 0) return FALSE;+ }+ while (set1 < set_end);+ }+ else+ {+ do+ {+ if ((*set1++ & *set2++) != 0) return FALSE;+ }+ while (set1 < set_end);+ }++ if (list[1] == 0) return TRUE;+ /* Might be an empty repeat. */+ continue;+ }++ /* Some property combinations also acceptable. Unicode property opcodes are+ processed specially; the rest can be handled with a lookup table. */++ else+ {+ uint32_t leftop, rightop;++ leftop = base_list[0];+ rightop = list[0];++#ifdef SUPPORT_UNICODE+ accepted = FALSE; /* Always set in non-unicode case. */+ if (leftop == OP_PROP || leftop == OP_NOTPROP)+ {+ if (rightop == OP_EOD)+ accepted = TRUE;+ else if (rightop == OP_PROP || rightop == OP_NOTPROP)+ {+ int n;+ const uint8_t *p;+ BOOL same = leftop == rightop;+ BOOL lisprop = leftop == OP_PROP;+ BOOL risprop = rightop == OP_PROP;+ BOOL bothprop = lisprop && risprop;++ /* There's a table that specifies how each combination is to be+ processed:+ 0 Always return FALSE (never auto-possessify)+ 1 Character groups are distinct (possessify if both are OP_PROP)+ 2 Check character categories in the same group (general or particular)+ 3 Return TRUE if the two opcodes are not the same+ ... see comments below+ */++ n = propposstab[base_list[2]][list[2]];+ switch(n)+ {+ case 0: break;+ case 1: accepted = bothprop; break;+ case 2: accepted = (base_list[3] == list[3]) != same; break;+ case 3: accepted = !same; break;++ case 4: /* Left general category, right particular category */+ accepted = risprop && catposstab[base_list[3]][list[3]] == same;+ break;++ case 5: /* Right general category, left particular category */+ accepted = lisprop && catposstab[list[3]][base_list[3]] == same;+ break;++ /* This code is logically tricky. Think hard before fiddling with it.+ The posspropstab table has four entries per row. Each row relates to+ one of PCRE's special properties such as ALNUM or SPACE or WORD.+ Only WORD actually needs all four entries, but using repeats for the+ others means they can all use the same code below.++ The first two entries in each row are Unicode general categories, and+ apply always, because all the characters they include are part of the+ PCRE character set. The third and fourth entries are a general and a+ particular category, respectively, that include one or more relevant+ characters. One or the other is used, depending on whether the check+ is for a general or a particular category. However, in both cases the+ category contains more characters than the specials that are defined+ for the property being tested against. Therefore, it cannot be used+ in a NOTPROP case.++ Example: the row for WORD contains ucp_L, ucp_N, ucp_P, ucp_Po.+ Underscore is covered by ucp_P or ucp_Po. */++ case 6: /* Left alphanum vs right general category */+ case 7: /* Left space vs right general category */+ case 8: /* Left word vs right general category */+ p = posspropstab[n-6];+ accepted = risprop && lisprop ==+ (list[3] != p[0] &&+ list[3] != p[1] &&+ (list[3] != p[2] || !lisprop));+ break;++ case 9: /* Right alphanum vs left general category */+ case 10: /* Right space vs left general category */+ case 11: /* Right word vs left general category */+ p = posspropstab[n-9];+ accepted = lisprop && risprop ==+ (base_list[3] != p[0] &&+ base_list[3] != p[1] &&+ (base_list[3] != p[2] || !risprop));+ break;++ case 12: /* Left alphanum vs right particular category */+ case 13: /* Left space vs right particular category */+ case 14: /* Left word vs right particular category */+ p = posspropstab[n-12];+ accepted = risprop && lisprop ==+ (catposstab[p[0]][list[3]] &&+ catposstab[p[1]][list[3]] &&+ (list[3] != p[3] || !lisprop));+ break;++ case 15: /* Right alphanum vs left particular category */+ case 16: /* Right space vs left particular category */+ case 17: /* Right word vs left particular category */+ p = posspropstab[n-15];+ accepted = lisprop && risprop ==+ (catposstab[p[0]][base_list[3]] &&+ catposstab[p[1]][base_list[3]] &&+ (base_list[3] != p[3] || !risprop));+ break;+ }+ }+ }++ else+#endif /* SUPPORT_UNICODE */++ accepted = leftop >= FIRST_AUTOTAB_OP && leftop <= LAST_AUTOTAB_LEFT_OP &&+ rightop >= FIRST_AUTOTAB_OP && rightop <= LAST_AUTOTAB_RIGHT_OP &&+ autoposstab[leftop - FIRST_AUTOTAB_OP][rightop - FIRST_AUTOTAB_OP];++ if (!accepted) return FALSE;++ if (list[1] == 0) return TRUE;+ /* Might be an empty repeat. */+ continue;+ }++ /* Control reaches here only if one of the items is a small character list.+ All characters are checked against the other side. */++ do+ {+ chr = *chr_ptr;++ switch(list_ptr[0])+ {+ case OP_CHAR:+ ochr_ptr = list_ptr + 2;+ do+ {+ if (chr == *ochr_ptr) return FALSE;+ ochr_ptr++;+ }+ while(*ochr_ptr != NOTACHAR);+ break;++ case OP_NOT:+ ochr_ptr = list_ptr + 2;+ do+ {+ if (chr == *ochr_ptr)+ break;+ ochr_ptr++;+ }+ while(*ochr_ptr != NOTACHAR);+ if (*ochr_ptr == NOTACHAR) return FALSE; /* Not found */+ break;++ /* Note that OP_DIGIT etc. are generated only when PCRE2_UCP is *not*+ set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */++ case OP_DIGIT:+ if (chr < 256 && (cb->ctypes[chr] & ctype_digit) != 0) return FALSE;+ break;++ case OP_NOT_DIGIT:+ if (chr > 255 || (cb->ctypes[chr] & ctype_digit) == 0) return FALSE;+ break;++ case OP_WHITESPACE:+ if (chr < 256 && (cb->ctypes[chr] & ctype_space) != 0) return FALSE;+ break;++ case OP_NOT_WHITESPACE:+ if (chr > 255 || (cb->ctypes[chr] & ctype_space) == 0) return FALSE;+ break;++ case OP_WORDCHAR:+ if (chr < 255 && (cb->ctypes[chr] & ctype_word) != 0) return FALSE;+ break;++ case OP_NOT_WORDCHAR:+ if (chr > 255 || (cb->ctypes[chr] & ctype_word) == 0) return FALSE;+ break;++ case OP_HSPACE:+ switch(chr)+ {+ HSPACE_CASES: return FALSE;+ default: break;+ }+ break;++ case OP_NOT_HSPACE:+ switch(chr)+ {+ HSPACE_CASES: break;+ default: return FALSE;+ }+ break;++ case OP_ANYNL:+ case OP_VSPACE:+ switch(chr)+ {+ VSPACE_CASES: return FALSE;+ default: break;+ }+ break;++ case OP_NOT_VSPACE:+ switch(chr)+ {+ VSPACE_CASES: break;+ default: return FALSE;+ }+ break;++ case OP_DOLL:+ case OP_EODN:+ switch (chr)+ {+ case CHAR_CR:+ case CHAR_LF:+ case CHAR_VT:+ case CHAR_FF:+ case CHAR_NEL:+#ifndef EBCDIC+ case 0x2028:+ case 0x2029:+#endif /* Not EBCDIC */+ return FALSE;+ }+ break;++ case OP_EOD: /* Can always possessify before \z */+ break;++#ifdef SUPPORT_UNICODE+ case OP_PROP:+ case OP_NOTPROP:+ if (!check_char_prop(chr, list_ptr[2], list_ptr[3],+ list_ptr[0] == OP_NOTPROP))+ return FALSE;+ break;+#endif++ case OP_NCLASS:+ if (chr > 255) return FALSE;+ /* Fall through */++ case OP_CLASS:+ if (chr > 255) break;+ class_bitset = (uint8_t *)+ ((list_ptr == list ? code : base_end) - list_ptr[2]);+ if ((class_bitset[chr >> 3] & (1u << (chr & 7))) != 0) return FALSE;+ break;++#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+ if (PRIV(xclass)(chr, (list_ptr == list ? code : base_end) -+ list_ptr[2] + LINK_SIZE, utf)) return FALSE;+ break;+#endif++ default:+ return FALSE;+ }++ chr_ptr++;+ }+ while(*chr_ptr != NOTACHAR);++ /* At least one character must be matched from this opcode. */++ if (list[1] == 0) return TRUE;+ }++/* Control never reaches here. There used to be a fail-save return FALSE; here,+but some compilers complain about an unreachable statement. */+}++++/*************************************************+* Scan compiled regex for auto-possession *+*************************************************/++/* Replaces single character iterations with their possessive alternatives+if appropriate. This function modifies the compiled opcode! Hitting a+non-existent opcode may indicate a bug in PCRE2, but it can also be caused if a+bad UTF string was compiled with PCRE2_NO_UTF_CHECK. The rec_limit catches+overly complicated or large patterns. In these cases, the check just stops,+leaving the remainder of the pattern unpossessified.++Arguments:+ code points to start of the byte code+ cb compile data block++Returns: 0 for success+ -1 if a non-existant opcode is encountered+*/++int+PRIV(auto_possessify)(PCRE2_UCHAR *code, const compile_block *cb)+{+PCRE2_UCHAR c;+PCRE2_SPTR end;+PCRE2_UCHAR *repeat_opcode;+uint32_t list[8];+int rec_limit = 1000; /* Was 10,000 but clang+ASAN uses a lot of stack. */+BOOL utf = (cb->external_options & PCRE2_UTF) != 0;+BOOL ucp = (cb->external_options & PCRE2_UCP) != 0;++for (;;)+ {+ c = *code;++ if (c >= OP_TABLE_LENGTH) return -1; /* Something gone wrong */++ if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)+ {+ c -= get_repeat_base(c) - OP_STAR;+ end = (c <= OP_MINUPTO) ?+ get_chr_property_list(code, utf, ucp, cb->fcc, list) : NULL;+ list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO;++ if (end != NULL && compare_opcodes(end, utf, ucp, cb, list, end,+ &rec_limit))+ {+ switch(c)+ {+ case OP_STAR:+ *code += OP_POSSTAR - OP_STAR;+ break;++ case OP_MINSTAR:+ *code += OP_POSSTAR - OP_MINSTAR;+ break;++ case OP_PLUS:+ *code += OP_POSPLUS - OP_PLUS;+ break;++ case OP_MINPLUS:+ *code += OP_POSPLUS - OP_MINPLUS;+ break;++ case OP_QUERY:+ *code += OP_POSQUERY - OP_QUERY;+ break;++ case OP_MINQUERY:+ *code += OP_POSQUERY - OP_MINQUERY;+ break;++ case OP_UPTO:+ *code += OP_POSUPTO - OP_UPTO;+ break;++ case OP_MINUPTO:+ *code += OP_POSUPTO - OP_MINUPTO;+ break;+ }+ }+ c = *code;+ }+ else if (c == OP_CLASS || c == OP_NCLASS || c == OP_XCLASS)+ {+#ifdef SUPPORT_WIDE_CHARS+ if (c == OP_XCLASS)+ repeat_opcode = code + GET(code, 1);+ else+#endif+ repeat_opcode = code + 1 + (32 / sizeof(PCRE2_UCHAR));++ c = *repeat_opcode;+ if (c >= OP_CRSTAR && c <= OP_CRMINRANGE)+ {+ /* end must not be NULL. */+ end = get_chr_property_list(code, utf, ucp, cb->fcc, list);++ list[1] = (c & 1) == 0;++ if (compare_opcodes(end, utf, ucp, cb, list, end, &rec_limit))+ {+ switch (c)+ {+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ *repeat_opcode = OP_CRPOSSTAR;+ break;++ case OP_CRPLUS:+ case OP_CRMINPLUS:+ *repeat_opcode = OP_CRPOSPLUS;+ break;++ case OP_CRQUERY:+ case OP_CRMINQUERY:+ *repeat_opcode = OP_CRPOSQUERY;+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ *repeat_opcode = OP_CRPOSRANGE;+ break;+ }+ }+ }+ c = *code;+ }++ switch(c)+ {+ case OP_END:+ return 0;++ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;+ break;++ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ case OP_TYPEPOSUPTO:+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)+ code += 2;+ break;++ case OP_CALLOUT_STR:+ code += GET(code, 1 + 2*LINK_SIZE);+ break;++#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+ code += GET(code, 1);+ break;+#endif++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ code += code[1];+ break;+ }++ /* Add in the fixed length from the table */++ code += PRIV(OP_lengths)[c];++ /* In UTF-8 and UTF-16 modes, opcodes that are followed by a character may be+ followed by a multi-byte character. The length in the table is a minimum, so+ we have to arrange to skip the extra code units. */++#ifdef MAYBE_UTF_MULTI+ if (utf) switch(c)+ {+ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ case OP_STAR:+ case OP_MINSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSPLUS:+ case OP_POSQUERY:+ case OP_POSUPTO:+ case OP_STARI:+ case OP_MINSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_EXACTI:+ case OP_POSSTARI:+ case OP_POSPLUSI:+ case OP_POSQUERYI:+ case OP_POSUPTOI:+ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTEXACT:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSUPTO:+ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTEXACTI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSUPTOI:+ if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);+ break;+ }+#else+ (void)(utf); /* Keep compiler happy by referencing function argument */+#endif /* SUPPORT_WIDE_CHARS */+ }+}++/* End of pcre2_auto_possess.c */
+ src/c/pcre2/src/pcre2_compile.c view
@@ -0,0 +1,10499 @@+/*************************************************+* 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) 2016-2020 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++#define NLBLOCK cb /* Block containing newline information */+#define PSSTART start_pattern /* Field containing processed string start */+#define PSEND end_pattern /* Field containing processed string end */++#include "pcre2_internal.h"++/* In rare error cases debugging might require calling pcre2_printint(). */++#if 0+#ifdef EBCDIC+#define PRINTABLE(c) ((c) >= 64 && (c) < 255)+#else+#define PRINTABLE(c) ((c) >= 32 && (c) < 127)+#endif+#include "pcre2_printint.c"+#define DEBUG_CALL_PRINTINT+#endif++/* Other debugging code can be enabled by these defines. */++/* #define DEBUG_SHOW_CAPTURES */+/* #define DEBUG_SHOW_PARSED */++/* There are a few things that vary with different code unit sizes. Handle them+by defining macros in order to minimize #if usage. */++#if PCRE2_CODE_UNIT_WIDTH == 8+#define STRING_UTFn_RIGHTPAR STRING_UTF8_RIGHTPAR, 5+#define XDIGIT(c) xdigitab[c]++#else /* Either 16-bit or 32-bit */+#define XDIGIT(c) (MAX_255(c)? xdigitab[c] : 0xff)++#if PCRE2_CODE_UNIT_WIDTH == 16+#define STRING_UTFn_RIGHTPAR STRING_UTF16_RIGHTPAR, 6++#else /* 32-bit */+#define STRING_UTFn_RIGHTPAR STRING_UTF32_RIGHTPAR, 6+#endif+#endif++/* Macros to store and retrieve a PCRE2_SIZE value in the parsed pattern, which+consists of uint32_t elements. Assume that if uint32_t can't hold it, two of+them will be able to (i.e. assume a 64-bit world). */++#if PCRE2_SIZE_MAX <= UINT32_MAX+#define PUTOFFSET(s,p) *p++ = s+#define GETOFFSET(s,p) s = *p+++#define GETPLUSOFFSET(s,p) s = *(++p)+#define READPLUSOFFSET(s,p) s = p[1]+#define SKIPOFFSET(p) p+++#define SIZEOFFSET 1+#else+#define PUTOFFSET(s,p) \+ { *p++ = (uint32_t)(s >> 32); *p++ = (uint32_t)(s & 0xffffffff); }+#define GETOFFSET(s,p) \+ { s = ((PCRE2_SIZE)p[0] << 32) | (PCRE2_SIZE)p[1]; p += 2; }+#define GETPLUSOFFSET(s,p) \+ { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; p += 2; }+#define READPLUSOFFSET(s,p) \+ { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; }+#define SKIPOFFSET(p) p += 2+#define SIZEOFFSET 2+#endif++/* Macros for manipulating elements of the parsed pattern vector. */++#define META_CODE(x) (x & 0xffff0000u)+#define META_DATA(x) (x & 0x0000ffffu)+#define META_DIFF(x,y) ((x-y)>>16)++/* Function definitions to allow mutual recursion */++#ifdef SUPPORT_UNICODE+static unsigned int+ add_list_to_class_internal(uint8_t *, PCRE2_UCHAR **, uint32_t,+ compile_block *, const uint32_t *, unsigned int);+#endif++static int+ compile_regex(uint32_t, PCRE2_UCHAR **, uint32_t **, int *, uint32_t,+ uint32_t *, int32_t *, uint32_t *, int32_t *, branch_chain *,+ compile_block *, PCRE2_SIZE *);++static int+ get_branchlength(uint32_t **, int *, int *, parsed_recurse_check *,+ compile_block *);++static BOOL+ set_lookbehind_lengths(uint32_t **, int *, int *, parsed_recurse_check *,+ compile_block *);++static int+ check_lookbehinds(uint32_t *, uint32_t **, parsed_recurse_check *,+ compile_block *);+++/*************************************************+* Code parameters and static tables *+*************************************************/++#define MAX_GROUP_NUMBER 65535u+#define MAX_REPEAT_COUNT 65535u+#define REPEAT_UNLIMITED (MAX_REPEAT_COUNT+1)++/* COMPILE_WORK_SIZE specifies the size of stack workspace, which is used in+different ways in the different pattern scans. The parsing and group-+identifying pre-scan uses it to handle nesting, and needs it to be 16-bit+aligned for this. Having defined the size in code units, we set up+C16_WORK_SIZE as the number of elements in the 16-bit vector.++During the first compiling phase, when determining how much memory is required,+the regex is partly compiled into this space, but the compiled parts are+discarded as soon as they can be, so that hopefully there will never be an+overrun. The code does, however, check for an overrun, which can occur for+pathological patterns. The size of the workspace depends on LINK_SIZE because+the length of compiled items varies with this.++In the real compile phase, this workspace is not currently used. */++#define COMPILE_WORK_SIZE (3000*LINK_SIZE) /* Size in code units */++#define C16_WORK_SIZE \+ ((COMPILE_WORK_SIZE * sizeof(PCRE2_UCHAR))/sizeof(uint16_t))++/* A uint32_t vector is used for caching information about the size of+capturing groups, to improve performance. A default is created on the stack of+this size. */++#define GROUPINFO_DEFAULT_SIZE 256++/* The overrun tests check for a slightly smaller size so that they detect the+overrun before it actually does run off the end of the data block. */++#define WORK_SIZE_SAFETY_MARGIN (100)++/* This value determines the size of the initial vector that is used for+remembering named groups during the pre-compile. It is allocated on the stack,+but if it is too small, it is expanded, in a similar way to the workspace. The+value is the number of slots in the list. */++#define NAMED_GROUP_LIST_SIZE 20++/* The pre-compiling pass over the pattern creates a parsed pattern in a vector+of uint32_t. For short patterns this lives on the stack, with this size. Heap+memory is used for longer patterns. */++#define PARSED_PATTERN_DEFAULT_SIZE 1024++/* Maximum length value to check against when making sure that the variable+that holds the compiled pattern length does not overflow. We make it a bit less+than INT_MAX to allow for adding in group terminating code units, so that we+don't have to check them every time. */++#define OFLOW_MAX (INT_MAX - 20)++/* Code values for parsed patterns, which are stored in a vector of 32-bit+unsigned ints. Values less than META_END are literal data values. The coding+for identifying the item is in the top 16-bits, leaving 16 bits for the+additional data that some of them need. The META_CODE, META_DATA, and META_DIFF+macros are used to manipulate parsed pattern elements.++NOTE: When these definitions are changed, the table of extra lengths for each+code (meta_extra_lengths, just below) must be updated to remain in step. */++#define META_END 0x80000000u /* End of pattern */++#define META_ALT 0x80010000u /* alternation */+#define META_ATOMIC 0x80020000u /* atomic group */+#define META_BACKREF 0x80030000u /* Back ref */+#define META_BACKREF_BYNAME 0x80040000u /* \k'name' */+#define META_BIGVALUE 0x80050000u /* Next is a literal > META_END */+#define META_CALLOUT_NUMBER 0x80060000u /* (?C with numerical argument */+#define META_CALLOUT_STRING 0x80070000u /* (?C with string argument */+#define META_CAPTURE 0x80080000u /* Capturing parenthesis */+#define META_CIRCUMFLEX 0x80090000u /* ^ metacharacter */+#define META_CLASS 0x800a0000u /* start non-empty class */+#define META_CLASS_EMPTY 0x800b0000u /* empty class */+#define META_CLASS_EMPTY_NOT 0x800c0000u /* negative empty class */+#define META_CLASS_END 0x800d0000u /* end of non-empty class */+#define META_CLASS_NOT 0x800e0000u /* start non-empty negative class */+#define META_COND_ASSERT 0x800f0000u /* (?(?assertion)... */+#define META_COND_DEFINE 0x80100000u /* (?(DEFINE)... */+#define META_COND_NAME 0x80110000u /* (?(<name>)... */+#define META_COND_NUMBER 0x80120000u /* (?(digits)... */+#define META_COND_RNAME 0x80130000u /* (?(R&name)... */+#define META_COND_RNUMBER 0x80140000u /* (?(Rdigits)... */+#define META_COND_VERSION 0x80150000u /* (?(VERSION<op>x.y)... */+#define META_DOLLAR 0x80160000u /* $ metacharacter */+#define META_DOT 0x80170000u /* . metacharacter */+#define META_ESCAPE 0x80180000u /* \d and friends */+#define META_KET 0x80190000u /* closing parenthesis */+#define META_NOCAPTURE 0x801a0000u /* no capture parens */+#define META_OPTIONS 0x801b0000u /* (?i) and friends */+#define META_POSIX 0x801c0000u /* POSIX class item */+#define META_POSIX_NEG 0x801d0000u /* negative POSIX class item */+#define META_RANGE_ESCAPED 0x801e0000u /* range with at least one escape */+#define META_RANGE_LITERAL 0x801f0000u /* range defined literally */+#define META_RECURSE 0x80200000u /* Recursion */+#define META_RECURSE_BYNAME 0x80210000u /* (?&name) */+#define META_SCRIPT_RUN 0x80220000u /* (*script_run:...) */++/* These must be kept together to make it easy to check that an assertion+is present where expected in a conditional group. */++#define META_LOOKAHEAD 0x80230000u /* (?= */+#define META_LOOKAHEADNOT 0x80240000u /* (?! */+#define META_LOOKBEHIND 0x80250000u /* (?<= */+#define META_LOOKBEHINDNOT 0x80260000u /* (?<! */++/* These cannot be conditions */++#define META_LOOKAHEAD_NA 0x80270000u /* (*napla: */+#define META_LOOKBEHIND_NA 0x80280000u /* (*naplb: */++/* These must be kept in this order, with consecutive values, and the _ARG+versions of COMMIT, PRUNE, SKIP, and THEN immediately after their non-argument+versions. */++#define META_MARK 0x80290000u /* (*MARK) */+#define META_ACCEPT 0x802a0000u /* (*ACCEPT) */+#define META_FAIL 0x802b0000u /* (*FAIL) */+#define META_COMMIT 0x802c0000u /* These */+#define META_COMMIT_ARG 0x802d0000u /* pairs */+#define META_PRUNE 0x802e0000u /* must */+#define META_PRUNE_ARG 0x802f0000u /* be */+#define META_SKIP 0x80300000u /* kept */+#define META_SKIP_ARG 0x80310000u /* in */+#define META_THEN 0x80320000u /* this */+#define META_THEN_ARG 0x80330000u /* order */++/* These must be kept in groups of adjacent 3 values, and all together. */++#define META_ASTERISK 0x80340000u /* * */+#define META_ASTERISK_PLUS 0x80350000u /* *+ */+#define META_ASTERISK_QUERY 0x80360000u /* *? */+#define META_PLUS 0x80370000u /* + */+#define META_PLUS_PLUS 0x80380000u /* ++ */+#define META_PLUS_QUERY 0x80390000u /* +? */+#define META_QUERY 0x803a0000u /* ? */+#define META_QUERY_PLUS 0x803b0000u /* ?+ */+#define META_QUERY_QUERY 0x803c0000u /* ?? */+#define META_MINMAX 0x803d0000u /* {n,m} repeat */+#define META_MINMAX_PLUS 0x803e0000u /* {n,m}+ repeat */+#define META_MINMAX_QUERY 0x803f0000u /* {n,m}? repeat */++#define META_FIRST_QUANTIFIER META_ASTERISK+#define META_LAST_QUANTIFIER META_MINMAX_QUERY++/* This is a special "meta code" that is used only to distinguish (*asr: from+(*sr: in the table of aphabetic assertions. It is never stored in the parsed+pattern because (*asr: is turned into (*sr:(*atomic: at that stage. There is+therefore no need for it to have a length entry, so use a high value. */++#define META_ATOMIC_SCRIPT_RUN 0x8fff0000u++/* Table of extra lengths for each of the meta codes. Must be kept in step with+the definitions above. For some items these values are a basic length to which+a variable amount has to be added. */++static unsigned char meta_extra_lengths[] = {+ 0, /* META_END */+ 0, /* META_ALT */+ 0, /* META_ATOMIC */+ 0, /* META_BACKREF - more if group is >= 10 */+ 1+SIZEOFFSET, /* META_BACKREF_BYNAME */+ 1, /* META_BIGVALUE */+ 3, /* META_CALLOUT_NUMBER */+ 3+SIZEOFFSET, /* META_CALLOUT_STRING */+ 0, /* META_CAPTURE */+ 0, /* META_CIRCUMFLEX */+ 0, /* META_CLASS */+ 0, /* META_CLASS_EMPTY */+ 0, /* META_CLASS_EMPTY_NOT */+ 0, /* META_CLASS_END */+ 0, /* META_CLASS_NOT */+ 0, /* META_COND_ASSERT */+ SIZEOFFSET, /* META_COND_DEFINE */+ 1+SIZEOFFSET, /* META_COND_NAME */+ 1+SIZEOFFSET, /* META_COND_NUMBER */+ 1+SIZEOFFSET, /* META_COND_RNAME */+ 1+SIZEOFFSET, /* META_COND_RNUMBER */+ 3, /* META_COND_VERSION */+ 0, /* META_DOLLAR */+ 0, /* META_DOT */+ 0, /* META_ESCAPE - more for ESC_P, ESC_p, ESC_g, ESC_k */+ 0, /* META_KET */+ 0, /* META_NOCAPTURE */+ 1, /* META_OPTIONS */+ 1, /* META_POSIX */+ 1, /* META_POSIX_NEG */+ 0, /* META_RANGE_ESCAPED */+ 0, /* META_RANGE_LITERAL */+ SIZEOFFSET, /* META_RECURSE */+ 1+SIZEOFFSET, /* META_RECURSE_BYNAME */+ 0, /* META_SCRIPT_RUN */+ 0, /* META_LOOKAHEAD */+ 0, /* META_LOOKAHEADNOT */+ SIZEOFFSET, /* META_LOOKBEHIND */+ SIZEOFFSET, /* META_LOOKBEHINDNOT */+ 0, /* META_LOOKAHEAD_NA */+ SIZEOFFSET, /* META_LOOKBEHIND_NA */+ 1, /* META_MARK - plus the string length */+ 0, /* META_ACCEPT */+ 0, /* META_FAIL */+ 0, /* META_COMMIT */+ 1, /* META_COMMIT_ARG - plus the string length */+ 0, /* META_PRUNE */+ 1, /* META_PRUNE_ARG - plus the string length */+ 0, /* META_SKIP */+ 1, /* META_SKIP_ARG - plus the string length */+ 0, /* META_THEN */+ 1, /* META_THEN_ARG - plus the string length */+ 0, /* META_ASTERISK */+ 0, /* META_ASTERISK_PLUS */+ 0, /* META_ASTERISK_QUERY */+ 0, /* META_PLUS */+ 0, /* META_PLUS_PLUS */+ 0, /* META_PLUS_QUERY */+ 0, /* META_QUERY */+ 0, /* META_QUERY_PLUS */+ 0, /* META_QUERY_QUERY */+ 2, /* META_MINMAX */+ 2, /* META_MINMAX_PLUS */+ 2 /* META_MINMAX_QUERY */+};++/* Types for skipping parts of a parsed pattern. */++enum { PSKIP_ALT, PSKIP_CLASS, PSKIP_KET };++/* Macro for setting individual bits in class bitmaps. It took some+experimenting to figure out how to stop gcc 5.3.0 from warning with+-Wconversion. This version gets a warning:++ #define SETBIT(a,b) a[(b)/8] |= (uint8_t)(1u << ((b)&7))++Let's hope the apparently less efficient version isn't actually so bad if the+compiler is clever with identical subexpressions. */++#define SETBIT(a,b) a[(b)/8] = (uint8_t)(a[(b)/8] | (1u << ((b)&7)))++/* Private flags added to firstcu and reqcu. */++#define REQ_CASELESS (1u << 0) /* Indicates caselessness */+#define REQ_VARY (1u << 1) /* reqcu followed non-literal item */+/* Negative values for the firstcu and reqcu flags */+#define REQ_UNSET (-2) /* Not yet found anything */+#define REQ_NONE (-1) /* Found not fixed char */++/* These flags are used in the groupinfo vector. */++#define GI_SET_FIXED_LENGTH 0x80000000u+#define GI_NOT_FIXED_LENGTH 0x40000000u+#define GI_FIXED_LENGTH_MASK 0x0000ffffu++/* This simple test for a decimal digit works for both ASCII/Unicode and EBCDIC+and is fast (a good compiler can turn it into a subtraction and unsigned+comparison). */++#define IS_DIGIT(x) ((x) >= CHAR_0 && (x) <= CHAR_9)++/* Table to identify hex digits. The tables in chartables are dependent on the+locale, and may mark arbitrary characters as digits. We want to recognize only+0-9, a-z, and A-Z as hex digits, which is why we have a private table here. It+costs 256 bytes, but it is a lot faster than doing character value tests (at+least in some simple cases I timed), and in some applications one wants PCRE2+to compile efficiently as well as match efficiently. The value in the table is+the binary hex digit value, or 0xff for non-hex digits. */++/* This is the "normal" case, for ASCII systems, and EBCDIC systems running in+UTF-8 mode. */++#ifndef EBCDIC+static const uint8_t xdigitab[] =+ {+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0- 7 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 8- 15 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 16- 23 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 24- 31 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - ' */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* ( - / */+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 0 - 7 */+ 0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff, /* 8 - ? */+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* @ - G */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* H - O */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* P - W */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* X - _ */+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* ` - g */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* h - o */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* p - w */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* x -127 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 128-135 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 136-143 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 144-151 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 152-159 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 160-167 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 168-175 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 176-183 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 184-191 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 192-199 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 2ff-207 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 208-215 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 216-223 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 224-231 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 232-239 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 240-247 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};/* 248-255 */++#else++/* This is the "abnormal" case, for EBCDIC systems not running in UTF-8 mode. */++static const uint8_t xdigitab[] =+ {+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0- 7 0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 8- 15 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 16- 23 10 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 24- 31 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 32- 39 20 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 40- 47 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 48- 55 30 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 56- 63 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - 71 40 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 72- | */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* & - 87 50 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 88- 95 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - -103 60 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 104- ? */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 112-119 70 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 120- " */+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* 128- g 80 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* h -143 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 144- p 90 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* q -159 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 160- x A0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* y -175 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* ^ -183 B0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 184-191 */+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* { - G C0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* H -207 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* } - P D0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* Q -223 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* \ - X E0 */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* Y -239 */+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 0 - 7 F0 */+ 0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff};/* 8 -255 */+#endif /* EBCDIC */+++/* Table for handling alphanumeric escaped characters. Positive returns are+simple data values; negative values are for special things like \d and so on.+Zero means further processing is needed (for things like \x), or the escape is+invalid. */++/* This is the "normal" table for ASCII systems or for EBCDIC systems running+in UTF-8 mode. It runs from '0' to 'z'. */++#ifndef EBCDIC+#define ESCAPES_FIRST CHAR_0+#define ESCAPES_LAST CHAR_z+#define UPPER_CASE(c) (c-32)++static const short int escapes[] = {+ 0, 0,+ 0, 0,+ 0, 0,+ 0, 0,+ 0, 0,+ CHAR_COLON, CHAR_SEMICOLON,+ CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN,+ CHAR_GREATER_THAN_SIGN, CHAR_QUESTION_MARK,+ CHAR_COMMERCIAL_AT, -ESC_A,+ -ESC_B, -ESC_C,+ -ESC_D, -ESC_E,+ 0, -ESC_G,+ -ESC_H, 0,+ 0, -ESC_K,+ 0, 0,+ -ESC_N, 0,+ -ESC_P, -ESC_Q,+ -ESC_R, -ESC_S,+ 0, 0,+ -ESC_V, -ESC_W,+ -ESC_X, 0,+ -ESC_Z, CHAR_LEFT_SQUARE_BRACKET,+ CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET,+ CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE,+ CHAR_GRAVE_ACCENT, CHAR_BEL,+ -ESC_b, 0,+ -ESC_d, CHAR_ESC,+ CHAR_FF, 0,+ -ESC_h, 0,+ 0, -ESC_k,+ 0, 0,+ CHAR_LF, 0,+ -ESC_p, 0,+ CHAR_CR, -ESC_s,+ CHAR_HT, 0,+ -ESC_v, -ESC_w,+ 0, 0,+ -ESC_z+};++#else++/* This is the "abnormal" table for EBCDIC systems without UTF-8 support.+It runs from 'a' to '9'. For some minimal testing of EBCDIC features, the code+is sometimes compiled on an ASCII system. In this case, we must not use CHAR_a+because it is defined as 'a', which of course picks up the ASCII value. */++#if 'a' == 0x81 /* Check for a real EBCDIC environment */+#define ESCAPES_FIRST CHAR_a+#define ESCAPES_LAST CHAR_9+#define UPPER_CASE(c) (c+64)+#else /* Testing in an ASCII environment */+#define ESCAPES_FIRST ((unsigned char)'\x81') /* EBCDIC 'a' */+#define ESCAPES_LAST ((unsigned char)'\xf9') /* EBCDIC '9' */+#define UPPER_CASE(c) (c-32)+#endif++static const short int escapes[] = {+/* 80 */ CHAR_BEL, -ESC_b, 0, -ESC_d, CHAR_ESC, CHAR_FF, 0,+/* 88 */ -ESC_h, 0, 0, '{', 0, 0, 0, 0,+/* 90 */ 0, 0, -ESC_k, 0, 0, CHAR_LF, 0, -ESC_p,+/* 98 */ 0, CHAR_CR, 0, '}', 0, 0, 0, 0,+/* A0 */ 0, '~', -ESC_s, CHAR_HT, 0, -ESC_v, -ESC_w, 0,+/* A8 */ 0, -ESC_z, 0, 0, 0, '[', 0, 0,+/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0,+/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-',+/* C0 */ '{', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G,+/* C8 */ -ESC_H, 0, 0, 0, 0, 0, 0, 0,+/* D0 */ '}', 0, -ESC_K, 0, 0, -ESC_N, 0, -ESC_P,+/* D8 */ -ESC_Q, -ESC_R, 0, 0, 0, 0, 0, 0,+/* E0 */ '\\', 0, -ESC_S, 0, 0, -ESC_V, -ESC_W, -ESC_X,+/* E8 */ 0, -ESC_Z, 0, 0, 0, 0, 0, 0,+/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0,+/* F8 */ 0, 0+};++/* We also need a table of characters that may follow \c in an EBCDIC+environment for characters 0-31. */++static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";++#endif /* EBCDIC */+++/* Table of special "verbs" like (*PRUNE). This is a short table, so it is+searched linearly. Put all the names into a single string, in order to reduce+the number of relocations when a shared library is dynamically linked. The+string is built from string macros so that it works in UTF-8 mode on EBCDIC+platforms. */++typedef struct verbitem {+ unsigned int len; /* Length of verb name */+ uint32_t meta; /* Base META_ code */+ int has_arg; /* Argument requirement */+} verbitem;++static const char verbnames[] =+ "\0" /* Empty name is a shorthand for MARK */+ STRING_MARK0+ STRING_ACCEPT0+ STRING_F0+ STRING_FAIL0+ STRING_COMMIT0+ STRING_PRUNE0+ STRING_SKIP0+ STRING_THEN;++static const verbitem verbs[] = {+ { 0, META_MARK, +1 }, /* > 0 => must have an argument */+ { 4, META_MARK, +1 },+ { 6, META_ACCEPT, -1 }, /* < 0 => Optional argument, convert to pre-MARK */+ { 1, META_FAIL, -1 },+ { 4, META_FAIL, -1 },+ { 6, META_COMMIT, 0 },+ { 5, META_PRUNE, 0 }, /* Optional argument; bump META code if found */+ { 4, META_SKIP, 0 },+ { 4, META_THEN, 0 }+};++static const int verbcount = sizeof(verbs)/sizeof(verbitem);++/* Verb opcodes, indexed by their META code offset from META_MARK. */++static const uint32_t verbops[] = {+ OP_MARK, OP_ACCEPT, OP_FAIL, OP_COMMIT, OP_COMMIT_ARG, OP_PRUNE,+ OP_PRUNE_ARG, OP_SKIP, OP_SKIP_ARG, OP_THEN, OP_THEN_ARG };++/* Table of "alpha assertions" like (*pla:...), similar to the (*VERB) table. */++typedef struct alasitem {+ unsigned int len; /* Length of name */+ uint32_t meta; /* Base META_ code */+} alasitem;++static const char alasnames[] =+ STRING_pla0+ STRING_plb0+ STRING_napla0+ STRING_naplb0+ STRING_nla0+ STRING_nlb0+ STRING_positive_lookahead0+ STRING_positive_lookbehind0+ STRING_non_atomic_positive_lookahead0+ STRING_non_atomic_positive_lookbehind0+ STRING_negative_lookahead0+ STRING_negative_lookbehind0+ STRING_atomic0+ STRING_sr0+ STRING_asr0+ STRING_script_run0+ STRING_atomic_script_run;++static const alasitem alasmeta[] = {+ { 3, META_LOOKAHEAD },+ { 3, META_LOOKBEHIND },+ { 5, META_LOOKAHEAD_NA },+ { 5, META_LOOKBEHIND_NA },+ { 3, META_LOOKAHEADNOT },+ { 3, META_LOOKBEHINDNOT },+ { 18, META_LOOKAHEAD },+ { 19, META_LOOKBEHIND },+ { 29, META_LOOKAHEAD_NA },+ { 30, META_LOOKBEHIND_NA },+ { 18, META_LOOKAHEADNOT },+ { 19, META_LOOKBEHINDNOT },+ { 6, META_ATOMIC },+ { 2, META_SCRIPT_RUN }, /* sr = script run */+ { 3, META_ATOMIC_SCRIPT_RUN }, /* asr = atomic script run */+ { 10, META_SCRIPT_RUN }, /* script run */+ { 17, META_ATOMIC_SCRIPT_RUN } /* atomic script run */+};++static const int alascount = sizeof(alasmeta)/sizeof(alasitem);++/* Offsets from OP_STAR for case-independent and negative repeat opcodes. */++static uint32_t chartypeoffset[] = {+ OP_STAR - OP_STAR, OP_STARI - OP_STAR,+ OP_NOTSTAR - OP_STAR, OP_NOTSTARI - OP_STAR };++/* Tables of names of POSIX character classes and their lengths. The names are+now all in a single string, to reduce the number of relocations when a shared+library is dynamically loaded. The list of lengths is terminated by a zero+length entry. The first three must be alpha, lower, upper, as this is assumed+for handling case independence. The indices for graph, print, and punct are+needed, so identify them. */++static const char posix_names[] =+ STRING_alpha0 STRING_lower0 STRING_upper0 STRING_alnum0+ STRING_ascii0 STRING_blank0 STRING_cntrl0 STRING_digit0+ STRING_graph0 STRING_print0 STRING_punct0 STRING_space0+ STRING_word0 STRING_xdigit;++static const uint8_t posix_name_lengths[] = {+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };++#define PC_GRAPH 8+#define PC_PRINT 9+#define PC_PUNCT 10++/* Table of class bit maps for each POSIX class. Each class is formed from a+base map, with an optional addition or removal of another map. Then, for some+classes, there is some additional tweaking: for [:blank:] the vertical space+characters are removed, and for [:alpha:] and [:alnum:] the underscore+character is removed. The triples in the table consist of the base map offset,+second map offset or -1 if no second map, and a non-negative value for map+addition or a negative value for map subtraction (if there are two maps). The+absolute value of the third field has these meanings: 0 => no tweaking, 1 =>+remove vertical space characters, 2 => remove underscore. */++static const int posix_class_maps[] = {+ cbit_word, cbit_digit, -2, /* alpha */+ cbit_lower, -1, 0, /* lower */+ cbit_upper, -1, 0, /* upper */+ cbit_word, -1, 2, /* alnum - word without underscore */+ cbit_print, cbit_cntrl, 0, /* ascii */+ cbit_space, -1, 1, /* blank - a GNU extension */+ cbit_cntrl, -1, 0, /* cntrl */+ cbit_digit, -1, 0, /* digit */+ cbit_graph, -1, 0, /* graph */+ cbit_print, -1, 0, /* print */+ cbit_punct, -1, 0, /* punct */+ cbit_space, -1, 0, /* space */+ cbit_word, -1, 0, /* word - a Perl extension */+ cbit_xdigit,-1, 0 /* xdigit */+};++#ifdef SUPPORT_UNICODE++/* The POSIX class Unicode property substitutes that are used in UCP mode must+be in the order of the POSIX class names, defined above. */++static int posix_substitutes[] = {+ PT_GC, ucp_L, /* alpha */+ PT_PC, ucp_Ll, /* lower */+ PT_PC, ucp_Lu, /* upper */+ PT_ALNUM, 0, /* alnum */+ -1, 0, /* ascii, treat as non-UCP */+ -1, 1, /* blank, treat as \h */+ PT_PC, ucp_Cc, /* cntrl */+ PT_PC, ucp_Nd, /* digit */+ PT_PXGRAPH, 0, /* graph */+ PT_PXPRINT, 0, /* print */+ PT_PXPUNCT, 0, /* punct */+ PT_PXSPACE, 0, /* space */ /* Xps is POSIX space, but from 8.34 */+ PT_WORD, 0, /* word */ /* Perl and POSIX space are the same */+ -1, 0 /* xdigit, treat as non-UCP */+};+#define POSIX_SUBSIZE (sizeof(posix_substitutes) / (2*sizeof(uint32_t)))+#endif /* SUPPORT_UNICODE */++/* Masks for checking option settings. When PCRE2_LITERAL is set, only a subset+are allowed. */++#define PUBLIC_LITERAL_COMPILE_OPTIONS \+ (PCRE2_ANCHORED|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_ENDANCHORED| \+ PCRE2_FIRSTLINE|PCRE2_LITERAL|PCRE2_MATCH_INVALID_UTF| \+ PCRE2_NO_START_OPTIMIZE|PCRE2_NO_UTF_CHECK|PCRE2_USE_OFFSET_LIMIT|PCRE2_UTF)++#define PUBLIC_COMPILE_OPTIONS \+ (PUBLIC_LITERAL_COMPILE_OPTIONS| \+ PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \+ PCRE2_ALT_VERBNAMES|PCRE2_DOLLAR_ENDONLY|PCRE2_DOTALL|PCRE2_DUPNAMES| \+ PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_MATCH_UNSET_BACKREF| \+ PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C|PCRE2_NEVER_UCP| \+ PCRE2_NEVER_UTF|PCRE2_NO_AUTO_CAPTURE|PCRE2_NO_AUTO_POSSESS| \+ PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_UCP|PCRE2_UNGREEDY)++#define PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS \+ (PCRE2_EXTRA_MATCH_LINE|PCRE2_EXTRA_MATCH_WORD)++#define PUBLIC_COMPILE_EXTRA_OPTIONS \+ (PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS| \+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES|PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL| \+ PCRE2_EXTRA_ESCAPED_CR_IS_LF|PCRE2_EXTRA_ALT_BSUX)++/* Compile time error code numbers. They are given names so that they can more+easily be tracked. When a new number is added, the tables called eint1 and+eint2 in pcre2posix.c may need to be updated, and a new error text must be+added to compile_error_texts in pcre2_error.c. */++enum { ERR0 = COMPILE_ERROR_BASE,+ ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10,+ ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20,+ ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, ERR30,+ ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40,+ ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, ERR50,+ ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, ERR60,+ ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70,+ ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80,+ ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90,+ ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98 };++/* This is a table of start-of-pattern options such as (*UTF) and settings such+as (*LIMIT_MATCH=nnnn) and (*CRLF). For completeness and backward+compatibility, (*UTFn) is supported in the relevant libraries, but (*UTF) is+generic and always supported. */++enum { PSO_OPT, /* Value is an option bit */+ PSO_FLG, /* Value is a flag bit */+ PSO_NL, /* Value is a newline type */+ PSO_BSR, /* Value is a \R type */+ PSO_LIMH, /* Read integer value for heap limit */+ PSO_LIMM, /* Read integer value for match limit */+ PSO_LIMD }; /* Read integer value for depth limit */++typedef struct pso {+ const uint8_t *name;+ uint16_t length;+ uint16_t type;+ uint32_t value;+} pso;++/* NB: STRING_UTFn_RIGHTPAR contains the length as well */++static pso pso_list[] = {+ { (uint8_t *)STRING_UTFn_RIGHTPAR, PSO_OPT, PCRE2_UTF },+ { (uint8_t *)STRING_UTF_RIGHTPAR, 4, PSO_OPT, PCRE2_UTF },+ { (uint8_t *)STRING_UCP_RIGHTPAR, 4, PSO_OPT, PCRE2_UCP },+ { (uint8_t *)STRING_NOTEMPTY_RIGHTPAR, 9, PSO_FLG, PCRE2_NOTEMPTY_SET },+ { (uint8_t *)STRING_NOTEMPTY_ATSTART_RIGHTPAR, 17, PSO_FLG, PCRE2_NE_ATST_SET },+ { (uint8_t *)STRING_NO_AUTO_POSSESS_RIGHTPAR, 16, PSO_OPT, PCRE2_NO_AUTO_POSSESS },+ { (uint8_t *)STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR, 18, PSO_OPT, PCRE2_NO_DOTSTAR_ANCHOR },+ { (uint8_t *)STRING_NO_JIT_RIGHTPAR, 7, PSO_FLG, PCRE2_NOJIT },+ { (uint8_t *)STRING_NO_START_OPT_RIGHTPAR, 13, PSO_OPT, PCRE2_NO_START_OPTIMIZE },+ { (uint8_t *)STRING_LIMIT_HEAP_EQ, 11, PSO_LIMH, 0 },+ { (uint8_t *)STRING_LIMIT_MATCH_EQ, 12, PSO_LIMM, 0 },+ { (uint8_t *)STRING_LIMIT_DEPTH_EQ, 12, PSO_LIMD, 0 },+ { (uint8_t *)STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMD, 0 },+ { (uint8_t *)STRING_CR_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_CR },+ { (uint8_t *)STRING_LF_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_LF },+ { (uint8_t *)STRING_CRLF_RIGHTPAR, 5, PSO_NL, PCRE2_NEWLINE_CRLF },+ { (uint8_t *)STRING_ANY_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_ANY },+ { (uint8_t *)STRING_NUL_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_NUL },+ { (uint8_t *)STRING_ANYCRLF_RIGHTPAR, 8, PSO_NL, PCRE2_NEWLINE_ANYCRLF },+ { (uint8_t *)STRING_BSR_ANYCRLF_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_ANYCRLF },+ { (uint8_t *)STRING_BSR_UNICODE_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_UNICODE }+};++/* This table is used when converting repeating opcodes into possessified+versions as a result of an explicit possessive quantifier such as ++. A zero+value means there is no possessified version - in those cases the item in+question must be wrapped in ONCE brackets. The table is truncated at OP_CALLOUT+because all relevant opcodes are less than that. */++static const uint8_t opcode_possessify[] = {+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 15 */+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 31 */++ 0, /* NOTI */+ OP_POSSTAR, 0, /* STAR, MINSTAR */+ OP_POSPLUS, 0, /* PLUS, MINPLUS */+ OP_POSQUERY, 0, /* QUERY, MINQUERY */+ OP_POSUPTO, 0, /* UPTO, MINUPTO */+ 0, /* EXACT */+ 0, 0, 0, 0, /* POS{STAR,PLUS,QUERY,UPTO} */++ OP_POSSTARI, 0, /* STARI, MINSTARI */+ OP_POSPLUSI, 0, /* PLUSI, MINPLUSI */+ OP_POSQUERYI, 0, /* QUERYI, MINQUERYI */+ OP_POSUPTOI, 0, /* UPTOI, MINUPTOI */+ 0, /* EXACTI */+ 0, 0, 0, 0, /* POS{STARI,PLUSI,QUERYI,UPTOI} */++ OP_NOTPOSSTAR, 0, /* NOTSTAR, NOTMINSTAR */+ OP_NOTPOSPLUS, 0, /* NOTPLUS, NOTMINPLUS */+ OP_NOTPOSQUERY, 0, /* NOTQUERY, NOTMINQUERY */+ OP_NOTPOSUPTO, 0, /* NOTUPTO, NOTMINUPTO */+ 0, /* NOTEXACT */+ 0, 0, 0, 0, /* NOTPOS{STAR,PLUS,QUERY,UPTO} */++ OP_NOTPOSSTARI, 0, /* NOTSTARI, NOTMINSTARI */+ OP_NOTPOSPLUSI, 0, /* NOTPLUSI, NOTMINPLUSI */+ OP_NOTPOSQUERYI, 0, /* NOTQUERYI, NOTMINQUERYI */+ OP_NOTPOSUPTOI, 0, /* NOTUPTOI, NOTMINUPTOI */+ 0, /* NOTEXACTI */+ 0, 0, 0, 0, /* NOTPOS{STARI,PLUSI,QUERYI,UPTOI} */++ OP_TYPEPOSSTAR, 0, /* TYPESTAR, TYPEMINSTAR */+ OP_TYPEPOSPLUS, 0, /* TYPEPLUS, TYPEMINPLUS */+ OP_TYPEPOSQUERY, 0, /* TYPEQUERY, TYPEMINQUERY */+ OP_TYPEPOSUPTO, 0, /* TYPEUPTO, TYPEMINUPTO */+ 0, /* TYPEEXACT */+ 0, 0, 0, 0, /* TYPEPOS{STAR,PLUS,QUERY,UPTO} */++ OP_CRPOSSTAR, 0, /* CRSTAR, CRMINSTAR */+ OP_CRPOSPLUS, 0, /* CRPLUS, CRMINPLUS */+ OP_CRPOSQUERY, 0, /* CRQUERY, CRMINQUERY */+ OP_CRPOSRANGE, 0, /* CRRANGE, CRMINRANGE */+ 0, 0, 0, 0, /* CRPOS{STAR,PLUS,QUERY,RANGE} */++ 0, 0, 0, /* CLASS, NCLASS, XCLASS */+ 0, 0, /* REF, REFI */+ 0, 0, /* DNREF, DNREFI */+ 0, 0 /* RECURSE, CALLOUT */+};+++#ifdef DEBUG_SHOW_PARSED+/*************************************************+* Show the parsed pattern for debugging *+*************************************************/++/* For debugging the pre-scan, this code, which outputs the parsed data vector,+can be enabled. */++static void show_parsed(compile_block *cb)+{+uint32_t *pptr = cb->parsed_pattern;++for (;;)+ {+ int max, min;+ PCRE2_SIZE offset;+ uint32_t i;+ uint32_t length;+ uint32_t meta_arg = META_DATA(*pptr);++ fprintf(stderr, "+++ %02d %.8x ", (int)(pptr - cb->parsed_pattern), *pptr);++ if (*pptr < META_END)+ {+ if (*pptr > 32 && *pptr < 128) fprintf(stderr, "%c", *pptr);+ pptr++;+ }++ else switch (META_CODE(*pptr++))+ {+ default:+ fprintf(stderr, "**** OOPS - unknown META value - giving up ****\n");+ return;++ case META_END:+ fprintf(stderr, "META_END\n");+ return;++ case META_CAPTURE:+ fprintf(stderr, "META_CAPTURE %d", meta_arg);+ break;++ case META_RECURSE:+ GETOFFSET(offset, pptr);+ fprintf(stderr, "META_RECURSE %d %zd", meta_arg, offset);+ break;++ case META_BACKREF:+ if (meta_arg < 10)+ offset = cb->small_ref_offset[meta_arg];+ else+ GETOFFSET(offset, pptr);+ fprintf(stderr, "META_BACKREF %d %zd", meta_arg, offset);+ break;++ case META_ESCAPE:+ if (meta_arg == ESC_P || meta_arg == ESC_p)+ {+ uint32_t ptype = *pptr >> 16;+ uint32_t pvalue = *pptr++ & 0xffff;+ fprintf(stderr, "META \\%c %d %d", (meta_arg == ESC_P)? 'P':'p',+ ptype, pvalue);+ }+ else+ {+ uint32_t cc;+ /* There's just one escape we might have here that isn't negated in the+ escapes table. */+ if (meta_arg == ESC_g) cc = CHAR_g;+ else for (cc = ESCAPES_FIRST; cc <= ESCAPES_LAST; cc++)+ {+ if (meta_arg == (uint32_t)(-escapes[cc - ESCAPES_FIRST])) break;+ }+ if (cc > ESCAPES_LAST) cc = CHAR_QUESTION_MARK;+ fprintf(stderr, "META \\%c", cc);+ }+ break;++ case META_MINMAX:+ min = *pptr++;+ max = *pptr++;+ if (max != REPEAT_UNLIMITED)+ fprintf(stderr, "META {%d,%d}", min, max);+ else+ fprintf(stderr, "META {%d,}", min);+ break;++ case META_MINMAX_QUERY:+ min = *pptr++;+ max = *pptr++;+ if (max != REPEAT_UNLIMITED)+ fprintf(stderr, "META {%d,%d}?", min, max);+ else+ fprintf(stderr, "META {%d,}?", min);+ break;++ case META_MINMAX_PLUS:+ min = *pptr++;+ max = *pptr++;+ if (max != REPEAT_UNLIMITED)+ fprintf(stderr, "META {%d,%d}+", min, max);+ else+ fprintf(stderr, "META {%d,}+", min);+ break;++ case META_BIGVALUE: fprintf(stderr, "META_BIGVALUE %.8x", *pptr++); break;+ case META_CIRCUMFLEX: fprintf(stderr, "META_CIRCUMFLEX"); break;+ case META_COND_ASSERT: fprintf(stderr, "META_COND_ASSERT"); break;+ case META_DOLLAR: fprintf(stderr, "META_DOLLAR"); break;+ case META_DOT: fprintf(stderr, "META_DOT"); break;+ case META_ASTERISK: fprintf(stderr, "META *"); break;+ case META_ASTERISK_QUERY: fprintf(stderr, "META *?"); break;+ case META_ASTERISK_PLUS: fprintf(stderr, "META *+"); break;+ case META_PLUS: fprintf(stderr, "META +"); break;+ case META_PLUS_QUERY: fprintf(stderr, "META +?"); break;+ case META_PLUS_PLUS: fprintf(stderr, "META ++"); break;+ case META_QUERY: fprintf(stderr, "META ?"); break;+ case META_QUERY_QUERY: fprintf(stderr, "META ??"); break;+ case META_QUERY_PLUS: fprintf(stderr, "META ?+"); break;++ case META_ATOMIC: fprintf(stderr, "META (?>"); break;+ case META_NOCAPTURE: fprintf(stderr, "META (?:"); break;+ case META_LOOKAHEAD: fprintf(stderr, "META (?="); break;+ case META_LOOKAHEADNOT: fprintf(stderr, "META (?!"); break;+ case META_LOOKAHEAD_NA: fprintf(stderr, "META (*napla:"); break;+ case META_SCRIPT_RUN: fprintf(stderr, "META (*sr:"); break;+ case META_KET: fprintf(stderr, "META )"); break;+ case META_ALT: fprintf(stderr, "META | %d", meta_arg); break;++ case META_CLASS: fprintf(stderr, "META ["); break;+ case META_CLASS_NOT: fprintf(stderr, "META [^"); break;+ case META_CLASS_END: fprintf(stderr, "META ]"); break;+ case META_CLASS_EMPTY: fprintf(stderr, "META []"); break;+ case META_CLASS_EMPTY_NOT: fprintf(stderr, "META [^]"); break;++ case META_RANGE_LITERAL: fprintf(stderr, "META - (literal)"); break;+ case META_RANGE_ESCAPED: fprintf(stderr, "META - (escaped)"); break;++ case META_POSIX: fprintf(stderr, "META_POSIX %d", *pptr++); break;+ case META_POSIX_NEG: fprintf(stderr, "META_POSIX_NEG %d", *pptr++); break;++ case META_ACCEPT: fprintf(stderr, "META (*ACCEPT)"); break;+ case META_FAIL: fprintf(stderr, "META (*FAIL)"); break;+ case META_COMMIT: fprintf(stderr, "META (*COMMIT)"); break;+ case META_PRUNE: fprintf(stderr, "META (*PRUNE)"); break;+ case META_SKIP: fprintf(stderr, "META (*SKIP)"); break;+ case META_THEN: fprintf(stderr, "META (*THEN)"); break;++ case META_OPTIONS: fprintf(stderr, "META_OPTIONS 0x%02x", *pptr++); break;++ case META_LOOKBEHIND:+ fprintf(stderr, "META (?<= %d offset=", meta_arg);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_LOOKBEHIND_NA:+ fprintf(stderr, "META (*naplb: %d offset=", meta_arg);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_LOOKBEHINDNOT:+ fprintf(stderr, "META (?<! %d offset=", meta_arg);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_CALLOUT_NUMBER:+ fprintf(stderr, "META (?C%d) next=%d/%d", pptr[2], pptr[0],+ pptr[1]);+ pptr += 3;+ break;++ case META_CALLOUT_STRING:+ {+ uint32_t patoffset = *pptr++; /* Offset of next pattern item */+ uint32_t patlength = *pptr++; /* Length of next pattern item */+ fprintf(stderr, "META (?Cstring) length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd next=%d/%d", offset, patoffset, patlength);+ }+ break;++ case META_RECURSE_BYNAME:+ fprintf(stderr, "META (?(&name) length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_BACKREF_BYNAME:+ fprintf(stderr, "META_BACKREF_BYNAME length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_COND_NUMBER:+ fprintf(stderr, "META_COND_NUMBER %d offset=", pptr[SIZEOFFSET]);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ pptr++;+ break;++ case META_COND_DEFINE:+ fprintf(stderr, "META (?(DEFINE) offset=");+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_COND_VERSION:+ fprintf(stderr, "META (?(VERSION%s", (*pptr++ == 0)? "=" : ">=");+ fprintf(stderr, "%d.", *pptr++);+ fprintf(stderr, "%d)", *pptr++);+ break;++ case META_COND_NAME:+ fprintf(stderr, "META (?(<name>) length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_COND_RNAME:+ fprintf(stderr, "META (?(R&name) length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ /* This is kept as a name, because it might be. */++ case META_COND_RNUMBER:+ fprintf(stderr, "META (?(Rnumber) length=%d offset=", *pptr++);+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_MARK:+ fprintf(stderr, "META (*MARK:");+ goto SHOWARG;++ case META_COMMIT_ARG:+ fprintf(stderr, "META (*COMMIT:");+ goto SHOWARG;++ case META_PRUNE_ARG:+ fprintf(stderr, "META (*PRUNE:");+ goto SHOWARG;++ case META_SKIP_ARG:+ fprintf(stderr, "META (*SKIP:");+ goto SHOWARG;++ case META_THEN_ARG:+ fprintf(stderr, "META (*THEN:");+ SHOWARG:+ length = *pptr++;+ for (i = 0; i < length; i++)+ {+ uint32_t cc = *pptr++;+ if (cc > 32 && cc < 128) fprintf(stderr, "%c", cc);+ else fprintf(stderr, "\\x{%x}", cc);+ }+ fprintf(stderr, ") length=%u", length);+ break;+ }+ fprintf(stderr, "\n");+ }+return;+}+#endif /* DEBUG_SHOW_PARSED */++++/*************************************************+* Copy compiled code *+*************************************************/++/* Compiled JIT code cannot be copied, so the new compiled block has no+associated JIT data. */++PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION+pcre2_code_copy(const pcre2_code *code)+{+PCRE2_SIZE* ref_count;+pcre2_code *newcode;++if (code == NULL) return NULL;+newcode = code->memctl.malloc(code->blocksize, code->memctl.memory_data);+if (newcode == NULL) return NULL;+memcpy(newcode, code, code->blocksize);+newcode->executable_jit = NULL;++/* If the code is one that has been deserialized, increment the reference count+in the decoded tables. */++if ((code->flags & PCRE2_DEREF_TABLES) != 0)+ {+ ref_count = (PCRE2_SIZE *)(code->tables + TABLES_LENGTH);+ (*ref_count)++;+ }++return newcode;+}++++/*************************************************+* Copy compiled code and character tables *+*************************************************/++/* Compiled JIT code cannot be copied, so the new compiled block has no+associated JIT data. This version of code_copy also makes a separate copy of+the character tables. */++PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION+pcre2_code_copy_with_tables(const pcre2_code *code)+{+PCRE2_SIZE* ref_count;+pcre2_code *newcode;+uint8_t *newtables;++if (code == NULL) return NULL;+newcode = code->memctl.malloc(code->blocksize, code->memctl.memory_data);+if (newcode == NULL) return NULL;+memcpy(newcode, code, code->blocksize);+newcode->executable_jit = NULL;++newtables = code->memctl.malloc(TABLES_LENGTH + sizeof(PCRE2_SIZE),+ code->memctl.memory_data);+if (newtables == NULL)+ {+ code->memctl.free((void *)newcode, code->memctl.memory_data);+ return NULL;+ }+memcpy(newtables, code->tables, TABLES_LENGTH);+ref_count = (PCRE2_SIZE *)(newtables + TABLES_LENGTH);+*ref_count = 1;++newcode->tables = newtables;+newcode->flags |= PCRE2_DEREF_TABLES;+return newcode;+}++++/*************************************************+* Free compiled code *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_code_free(pcre2_code *code)+{+PCRE2_SIZE* ref_count;++if (code != NULL)+ {+ if (code->executable_jit != NULL)+ PRIV(jit_free)(code->executable_jit, &code->memctl);++ if ((code->flags & PCRE2_DEREF_TABLES) != 0)+ {+ /* Decoded tables belong to the codes after deserialization, and they must+ be freed when there are no more references to them. The *ref_count should+ always be > 0. */++ ref_count = (PCRE2_SIZE *)(code->tables + TABLES_LENGTH);+ if (*ref_count > 0)+ {+ (*ref_count)--;+ if (*ref_count == 0)+ code->memctl.free((void *)code->tables, code->memctl.memory_data);+ }+ }++ code->memctl.free(code, code->memctl.memory_data);+ }+}++++/*************************************************+* Read a number, possibly signed *+*************************************************/++/* This function is used to read numbers in the pattern. The initial pointer+must be the sign or first digit of the number. When relative values (introduced+by + or -) are allowed, they are relative group numbers, and the result must be+greater than zero.++Arguments:+ ptrptr points to the character pointer variable+ ptrend points to the end of the input string+ allow_sign if < 0, sign not allowed; if >= 0, sign is relative to this+ max_value the largest number allowed+ max_error the error to give for an over-large number+ intptr where to put the result+ errcodeptr where to put an error code++Returns: TRUE - a number was read+ FALSE - errorcode == 0 => no number was found+ errorcode != 0 => an error occurred+*/++static BOOL+read_number(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, int32_t allow_sign,+ uint32_t max_value, uint32_t max_error, int *intptr, int *errorcodeptr)+{+int sign = 0;+uint32_t n = 0;+PCRE2_SPTR ptr = *ptrptr;+BOOL yield = FALSE;++*errorcodeptr = 0;++if (allow_sign >= 0 && ptr < ptrend)+ {+ if (*ptr == CHAR_PLUS)+ {+ sign = +1;+ max_value -= allow_sign;+ ptr++;+ }+ else if (*ptr == CHAR_MINUS)+ {+ sign = -1;+ ptr++;+ }+ }++if (ptr >= ptrend || !IS_DIGIT(*ptr)) return FALSE;+while (ptr < ptrend && IS_DIGIT(*ptr))+ {+ n = n * 10 + *ptr++ - CHAR_0;+ if (n > max_value)+ {+ *errorcodeptr = max_error;+ goto EXIT;+ }+ }++if (allow_sign >= 0 && sign != 0)+ {+ if (n == 0)+ {+ *errorcodeptr = ERR26; /* +0 and -0 are not allowed */+ goto EXIT;+ }++ if (sign > 0) n += allow_sign;+ else if ((int)n > allow_sign)+ {+ *errorcodeptr = ERR15; /* Non-existent subpattern */+ goto EXIT;+ }+ else n = allow_sign + 1 - n;+ }++yield = TRUE;++EXIT:+*intptr = n;+*ptrptr = ptr;+return yield;+}++++/*************************************************+* Read repeat counts *+*************************************************/++/* Read an item of the form {n,m} and return the values if non-NULL pointers+are supplied. Repeat counts must be less than 65536 (MAX_REPEAT_COUNT); a+larger value is used for "unlimited". We have to use signed arguments for+read_number() because it is capable of returning a signed value.++Arguments:+ ptrptr points to pointer to character after'{'+ ptrend pointer to end of input+ minp if not NULL, pointer to int for min+ maxp if not NULL, pointer to int for max (-1 if no max)+ returned as -1 if no max+ errorcodeptr points to error code variable++Returns: FALSE if not a repeat quantifier, errorcode set zero+ FALSE on error, with errorcode set non-zero+ TRUE on success, with pointer updated to point after '}'+*/++static BOOL+read_repeat_counts(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *minp,+ uint32_t *maxp, int *errorcodeptr)+{+PCRE2_SPTR p = *ptrptr;+BOOL yield = FALSE;+int32_t min = 0;+int32_t max = REPEAT_UNLIMITED; /* This value is larger than MAX_REPEAT_COUNT */++/* NB read_number() initializes the error code to zero. The only error is for a+number that is too big. */++if (!read_number(&p, ptrend, -1, MAX_REPEAT_COUNT, ERR5, &min, errorcodeptr))+ goto EXIT;++if (p >= ptrend) goto EXIT;++if (*p == CHAR_RIGHT_CURLY_BRACKET)+ {+ p++;+ max = min;+ }++else+ {+ if (*p++ != CHAR_COMMA || p >= ptrend) goto EXIT;+ if (*p != CHAR_RIGHT_CURLY_BRACKET)+ {+ if (!read_number(&p, ptrend, -1, MAX_REPEAT_COUNT, ERR5, &max,+ errorcodeptr) || p >= ptrend || *p != CHAR_RIGHT_CURLY_BRACKET)+ goto EXIT;+ if (max < min)+ {+ *errorcodeptr = ERR4;+ goto EXIT;+ }+ }+ p++;+ }++yield = TRUE;+if (minp != NULL) *minp = (uint32_t)min;+if (maxp != NULL) *maxp = (uint32_t)max;++/* Update the pattern pointer on success, or after an error, but not when+the result is "not a repeat quantifier". */++EXIT:+if (yield || *errorcodeptr != 0) *ptrptr = p;+return yield;+}++++/*************************************************+* Handle escapes *+*************************************************/++/* This function is called when a \ has been encountered. It either returns a+positive value for a simple escape such as \d, or 0 for a data character, which+is placed in chptr. A backreference to group n is returned as negative n. On+entry, ptr is pointing at the character after \. On exit, it points after the+final code unit of the escape sequence.++This function is also called from pcre2_substitute() to handle escape sequences+in replacement strings. In this case, the cb argument is NULL, and in the case+of escapes that have further processing, only sequences that define a data+character are recognised. The isclass argument is not relevant; the options+argument is the final value of the compiled pattern's options.++Arguments:+ ptrptr points to the input position pointer+ ptrend points to the end of the input+ chptr points to a returned data character+ errorcodeptr points to the errorcode variable (containing zero)+ options the current options bits+ isclass TRUE if inside a character class+ cb compile data block or NULL when called from pcre2_substitute()++Returns: zero => a data character+ positive => a special escape sequence+ negative => a numerical back reference+ on error, errorcodeptr is set non-zero+*/++int+PRIV(check_escape)(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *chptr,+ int *errorcodeptr, uint32_t options, uint32_t extra_options, BOOL isclass,+ compile_block *cb)+{+BOOL utf = (options & PCRE2_UTF) != 0;+PCRE2_SPTR ptr = *ptrptr;+uint32_t c, cc;+int escape = 0;+int i;++/* If backslash is at the end of the string, it's an error. */++if (ptr >= ptrend)+ {+ *errorcodeptr = ERR1;+ return 0;+ }++GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */+*errorcodeptr = 0; /* Be optimistic */++/* Non-alphanumerics are literals, so we just leave the value in c. An initial+value test saves a memory lookup for code points outside the alphanumeric+range. */++if (c < ESCAPES_FIRST || c > ESCAPES_LAST) {} /* Definitely literal */++/* Otherwise, do a table lookup. Non-zero values need little processing here. A+positive value is a literal value for something like \n. A negative value is+the negation of one of the ESC_ macros that is passed back for handling by the+calling function. Some extra checking is needed for \N because only \N{U+dddd}+is supported. If the value is zero, further processing is handled below. */++else if ((i = escapes[c - ESCAPES_FIRST]) != 0)+ {+ if (i > 0)+ {+ c = (uint32_t)i;+ if (c == CHAR_CR && (extra_options & PCRE2_EXTRA_ESCAPED_CR_IS_LF) != 0)+ c = CHAR_LF;+ }+ else /* Negative table entry */+ {+ escape = -i; /* Else return a special escape */+ if (cb != NULL && (escape == ESC_P || escape == ESC_p || escape == ESC_X))+ cb->external_flags |= PCRE2_HASBKPORX; /* Note \P, \p, or \X */++ /* Perl supports \N{name} for character names and \N{U+dddd} for numerical+ Unicode code points, as well as plain \N for "not newline". PCRE does not+ support \N{name}. However, it does support quantification such as \N{2,3},+ so if \N{ is not followed by U+dddd we check for a quantifier. */++ if (escape == ESC_N && ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET)+ {+ PCRE2_SPTR p = ptr + 1;++ /* \N{U+ can be handled by the \x{ code. However, this construction is+ not valid in EBCDIC environments because it specifies a Unicode+ character, not a codepoint in the local code. For example \N{U+0041}+ must be "A" in all environments. Also, in Perl, \N{U+ forces Unicode+ casing semantics for the entire pattern, so allow it only in UTF (i.e.+ Unicode) mode. */++ if (ptrend - p > 1 && *p == CHAR_U && p[1] == CHAR_PLUS)+ {+#ifdef EBCDIC+ *errorcodeptr = ERR93;+#else+ if (utf)+ {+ ptr = p + 1;+ escape = 0; /* Not a fancy escape after all */+ goto COME_FROM_NU;+ }+ else *errorcodeptr = ERR93;+#endif+ }++ /* Give an error if what follows is not a quantifier, but don't override+ an error set by the quantifier reader (e.g. number overflow). */++ else+ {+ if (!read_repeat_counts(&p, ptrend, NULL, NULL, errorcodeptr) &&+ *errorcodeptr == 0)+ *errorcodeptr = ERR37;+ }+ }+ }+ }++/* Escapes that need further processing, including those that are unknown, have+a zero entry in the lookup table. When called from pcre2_substitute(), only \c,+\o, and \x are recognized (\u and \U can never appear as they are used for case+forcing). */++else+ {+ int s;+ PCRE2_SPTR oldptr;+ BOOL overflow;+ BOOL alt_bsux =+ ((options & PCRE2_ALT_BSUX) | (extra_options & PCRE2_EXTRA_ALT_BSUX)) != 0;++ /* Filter calls from pcre2_substitute(). */++ if (cb == NULL)+ {+ if (c != CHAR_c && c != CHAR_o && c != CHAR_x)+ {+ *errorcodeptr = ERR3;+ return 0;+ }+ alt_bsux = FALSE; /* Do not modify \x handling */+ }++ switch (c)+ {+ /* A number of Perl escapes are not handled by PCRE. We give an explicit+ error. */++ case CHAR_F:+ case CHAR_l:+ case CHAR_L:+ *errorcodeptr = ERR37;+ break;++ /* \u is unrecognized when neither PCRE2_ALT_BSUX nor PCRE2_EXTRA_ALT_BSUX+ is set. Otherwise, \u must be followed by exactly four hex digits or, if+ PCRE2_EXTRA_ALT_BSUX is set, by any number of hex digits in braces.+ Otherwise it is a lowercase u letter. This gives some compatibility with+ ECMAScript (aka JavaScript). */++ case CHAR_u:+ if (!alt_bsux) *errorcodeptr = ERR37; else+ {+ uint32_t xc;++ if (ptr >= ptrend) break;+ if (*ptr == CHAR_LEFT_CURLY_BRACKET &&+ (extra_options & PCRE2_EXTRA_ALT_BSUX) != 0)+ {+ PCRE2_SPTR hptr = ptr + 1;+ cc = 0;++ while (hptr < ptrend && (xc = XDIGIT(*hptr)) != 0xff)+ {+ if ((cc & 0xf0000000) != 0) /* Test for 32-bit overflow */+ {+ *errorcodeptr = ERR77;+ ptr = hptr; /* Show where */+ break; /* *hptr != } will cause another break below */+ }+ cc = (cc << 4) | xc;+ hptr++;+ }++ if (hptr == ptr + 1 || /* No hex digits */+ hptr >= ptrend || /* Hit end of input */+ *hptr != CHAR_RIGHT_CURLY_BRACKET) /* No } terminator */+ break; /* Hex escape not recognized */++ c = cc; /* Accept the code point */+ ptr = hptr + 1;+ }++ else /* Must be exactly 4 hex digits */+ {+ if (ptrend - ptr < 4) break; /* Less than 4 chars */+ if ((cc = XDIGIT(ptr[0])) == 0xff) break; /* Not a hex digit */+ if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */+ cc = (cc << 4) | xc;+ if ((xc = XDIGIT(ptr[2])) == 0xff) break; /* Not a hex digit */+ cc = (cc << 4) | xc;+ if ((xc = XDIGIT(ptr[3])) == 0xff) break; /* Not a hex digit */+ c = (cc << 4) | xc;+ ptr += 4;+ }++ if (utf)+ {+ if (c > 0x10ffffU) *errorcodeptr = ERR77;+ else+ if (c >= 0xd800 && c <= 0xdfff &&+ (extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)+ *errorcodeptr = ERR73;+ }+ else if (c > MAX_NON_UTF_CHAR) *errorcodeptr = ERR77;+ }+ break;++ /* \U is unrecognized unless PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set,+ in which case it is an upper case letter. */++ case CHAR_U:+ if (!alt_bsux) *errorcodeptr = ERR37;+ break;++ /* In a character class, \g is just a literal "g". Outside a character+ class, \g must be followed by one of a number of specific things:++ (1) A number, either plain or braced. If positive, it is an absolute+ backreference. If negative, it is a relative backreference. This is a Perl+ 5.10 feature.++ (2) Perl 5.10 also supports \g{name} as a reference to a named group. This+ is part of Perl's movement towards a unified syntax for back references. As+ this is synonymous with \k{name}, we fudge it up by pretending it really+ was \k{name}.++ (3) For Oniguruma compatibility we also support \g followed by a name or a+ number either in angle brackets or in single quotes. However, these are+ (possibly recursive) subroutine calls, _not_ backreferences. We return+ the ESC_g code.++ Summary: Return a negative number for a numerical back reference, ESC_k for+ a named back reference, and ESC_g for a named or numbered subroutine call.+ */++ case CHAR_g:+ if (isclass) break;++ if (ptr >= ptrend)+ {+ *errorcodeptr = ERR57;+ break;+ }++ if (*ptr == CHAR_LESS_THAN_SIGN || *ptr == CHAR_APOSTROPHE)+ {+ escape = ESC_g;+ break;+ }++ /* If there is a brace delimiter, try to read a numerical reference. If+ there isn't one, assume we have a name and treat it as \k. */++ if (*ptr == CHAR_LEFT_CURLY_BRACKET)+ {+ PCRE2_SPTR p = ptr + 1;+ if (!read_number(&p, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &s,+ errorcodeptr))+ {+ if (*errorcodeptr == 0) escape = ESC_k; /* No number found */+ break;+ }+ if (p >= ptrend || *p != CHAR_RIGHT_CURLY_BRACKET)+ {+ *errorcodeptr = ERR57;+ break;+ }+ ptr = p + 1;+ }++ /* Read an undelimited number */++ else+ {+ if (!read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &s,+ errorcodeptr))+ {+ if (*errorcodeptr == 0) *errorcodeptr = ERR57; /* No number found */+ break;+ }+ }++ if (s <= 0)+ {+ *errorcodeptr = ERR15;+ break;+ }++ escape = -s;+ break;++ /* The handling of escape sequences consisting of a string of digits+ starting with one that is not zero is not straightforward. Perl has changed+ over the years. Nowadays \g{} for backreferences and \o{} for octal are+ recommended to avoid the ambiguities in the old syntax.++ Outside a character class, the digits are read as a decimal number. If the+ number is less than 10, or if there are that many previous extracting left+ brackets, it is a back reference. Otherwise, up to three octal digits are+ read to form an escaped character code. Thus \123 is likely to be octal 123+ (cf \0123, which is octal 012 followed by the literal 3).++ Inside a character class, \ followed by a digit is always either a literal+ 8 or 9 or an octal number. */++ case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5:+ case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:++ if (!isclass)+ {+ oldptr = ptr;+ ptr--; /* Back to the digit */+ if (!read_number(&ptr, ptrend, -1, INT_MAX/10 - 1, ERR61, &s,+ errorcodeptr))+ break;++ /* \1 to \9 are always back references. \8x and \9x are too; \1x to \7x+ are octal escapes if there are not that many previous captures. */++ if (s < 10 || oldptr[-1] >= CHAR_8 || s <= (int)cb->bracount)+ {+ if (s > (int)MAX_GROUP_NUMBER) *errorcodeptr = ERR61;+ else escape = -s; /* Indicates a back reference */+ break;+ }+ ptr = oldptr; /* Put the pointer back and fall through */+ }++ /* Handle a digit following \ when the number is not a back reference, or+ we are within a character class. If the first digit is 8 or 9, Perl used to+ generate a binary zero and then treat the digit as a following literal. At+ least by Perl 5.18 this changed so as not to insert the binary zero. */++ if (c >= CHAR_8) break;++ /* Fall through */++ /* \0 always starts an octal number, but we may drop through to here with a+ larger first octal digit. The original code used just to take the least+ significant 8 bits of octal numbers (I think this is what early Perls used+ to do). Nowadays we allow for larger numbers in UTF-8 mode and 16-bit mode,+ but no more than 3 octal digits. */++ case CHAR_0:+ c -= CHAR_0;+ while(i++ < 2 && ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7)+ c = c * 8 + *ptr++ - CHAR_0;+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (!utf && c > 0xff) *errorcodeptr = ERR51;+#endif+ break;++ /* \o is a relatively new Perl feature, supporting a more general way of+ specifying character codes in octal. The only supported form is \o{ddd}. */++ case CHAR_o:+ if (ptr >= ptrend || *ptr++ != CHAR_LEFT_CURLY_BRACKET)+ {+ ptr--;+ *errorcodeptr = ERR55;+ }+ else if (ptr >= ptrend || *ptr == CHAR_RIGHT_CURLY_BRACKET)+ *errorcodeptr = ERR78;+ else+ {+ c = 0;+ overflow = FALSE;+ while (ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7)+ {+ cc = *ptr++;+ if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c >= 0x20000000l) { overflow = TRUE; break; }+#endif+ c = (c << 3) + (cc - CHAR_0);+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (c > (utf ? 0x10ffffU : 0xffU)) { overflow = TRUE; break; }+#elif PCRE2_CODE_UNIT_WIDTH == 16+ if (c > (utf ? 0x10ffffU : 0xffffU)) { overflow = TRUE; break; }+#elif PCRE2_CODE_UNIT_WIDTH == 32+ if (utf && c > 0x10ffffU) { overflow = TRUE; break; }+#endif+ }+ if (overflow)+ {+ while (ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7) ptr++;+ *errorcodeptr = ERR34;+ }+ else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)+ {+ if (utf && c >= 0xd800 && c <= 0xdfff &&+ (extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)+ {+ ptr--;+ *errorcodeptr = ERR73;+ }+ }+ else+ {+ ptr--;+ *errorcodeptr = ERR64;+ }+ }+ break;++ /* When PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set, \x must be followed+ by two hexadecimal digits. Otherwise it is a lowercase x letter. */++ case CHAR_x:+ if (alt_bsux)+ {+ uint32_t xc;+ if (ptrend - ptr < 2) break; /* Less than 2 characters */+ if ((cc = XDIGIT(ptr[0])) == 0xff) break; /* Not a hex digit */+ if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */+ c = (cc << 4) | xc;+ ptr += 2;+ }++ /* Handle \x in Perl's style. \x{ddd} is a character code which can be+ greater than 0xff in UTF-8 or non-8bit mode, but only if the ddd are hex+ digits. If not, { used to be treated as a data character. However, Perl+ seems to read hex digits up to the first non-such, and ignore the rest, so+ that, for example \x{zz} matches a binary zero. This seems crazy, so PCRE+ now gives an error. */++ else+ {+ if (ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET)+ {+#ifndef EBCDIC+ COME_FROM_NU:+#endif+ if (++ptr >= ptrend || *ptr == CHAR_RIGHT_CURLY_BRACKET)+ {+ *errorcodeptr = ERR78;+ break;+ }+ c = 0;+ overflow = FALSE;++ while (ptr < ptrend && (cc = XDIGIT(*ptr)) != 0xff)+ {+ ptr++;+ if (c == 0 && cc == 0) continue; /* Leading zeroes */+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c >= 0x10000000l) { overflow = TRUE; break; }+#endif+ c = (c << 4) | cc;+ if ((utf && c > 0x10ffffU) || (!utf && c > MAX_NON_UTF_CHAR))+ {+ overflow = TRUE;+ break;+ }+ }++ if (overflow)+ {+ while (ptr < ptrend && XDIGIT(*ptr) != 0xff) ptr++;+ *errorcodeptr = ERR34;+ }+ else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)+ {+ if (utf && c >= 0xd800 && c <= 0xdfff &&+ (extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)+ {+ ptr--;+ *errorcodeptr = ERR73;+ }+ }++ /* If the sequence of hex digits does not end with '}', give an error.+ We used just to recognize this construct and fall through to the normal+ \x handling, but nowadays Perl gives an error, which seems much more+ sensible, so we do too. */++ else+ {+ ptr--;+ *errorcodeptr = ERR67;+ }+ } /* End of \x{} processing */++ /* Read a up to two hex digits after \x */++ else+ {+ c = 0;+ if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) break; /* Not a hex digit */+ ptr++;+ c = cc;+ if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) break; /* Not a hex digit */+ ptr++;+ c = (c << 4) | cc;+ } /* End of \xdd handling */+ } /* End of Perl-style \x handling */+ break;++ /* The handling of \c is different in ASCII and EBCDIC environments. In an+ ASCII (or Unicode) environment, an error is given if the character+ following \c is not a printable ASCII character. Otherwise, the following+ character is upper-cased if it is a letter, and after that the 0x40 bit is+ flipped. The result is the value of the escape.++ In an EBCDIC environment the handling of \c is compatible with the+ specification in the perlebcdic document. The following character must be+ a letter or one of small number of special characters. These provide a+ means of defining the character values 0-31.++ For testing the EBCDIC handling of \c in an ASCII environment, recognize+ the EBCDIC value of 'c' explicitly. */++#if defined EBCDIC && 'a' != 0x81+ case 0x83:+#else+ case CHAR_c:+#endif+ if (ptr >= ptrend)+ {+ *errorcodeptr = ERR2;+ break;+ }+ c = *ptr;+ if (c >= CHAR_a && c <= CHAR_z) c = UPPER_CASE(c);++ /* Handle \c in an ASCII/Unicode environment. */++#ifndef EBCDIC /* ASCII/UTF-8 coding */+ if (c < 32 || c > 126) /* Excludes all non-printable ASCII */+ {+ *errorcodeptr = ERR68;+ break;+ }+ c ^= 0x40;++ /* Handle \c in an EBCDIC environment. The special case \c? is converted to+ 255 (0xff) or 95 (0x5f) if other characters suggest we are using the+ POSIX-BC encoding. (This is the way Perl indicates that it handles \c?.)+ The other valid sequences correspond to a list of specific characters. */++#else+ if (c == CHAR_QUESTION_MARK)+ c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff;+ else+ {+ for (i = 0; i < 32; i++)+ {+ if (c == ebcdic_escape_c[i]) break;+ }+ if (i < 32) c = i; else *errorcodeptr = ERR68;+ }+#endif /* EBCDIC */++ ptr++;+ break;++ /* Any other alphanumeric following \ is an error. Perl gives an error only+ if in warning mode, but PCRE doesn't have a warning mode. */++ default:+ *errorcodeptr = ERR3;+ *ptrptr = ptr - 1; /* Point to the character at fault */+ return 0;+ }+ }++/* Set the pointer to the next character before returning. */++*ptrptr = ptr;+*chptr = c;+return escape;+}++++#ifdef SUPPORT_UNICODE+/*************************************************+* Handle \P and \p *+*************************************************/++/* This function is called after \P or \p has been encountered, provided that+PCRE2 is compiled with support for UTF and Unicode properties. On entry, the+contents of ptrptr are pointing after the P or p. On exit, it is left pointing+after the final code unit of the escape sequence.++Arguments:+ ptrptr the pattern position pointer+ negptr a boolean that is set TRUE for negation else FALSE+ ptypeptr an unsigned int that is set to the type value+ pdataptr an unsigned int that is set to the detailed property value+ errorcodeptr the error code variable+ cb the compile data++Returns: TRUE if the type value was found, or FALSE for an invalid type+*/++static BOOL+get_ucp(PCRE2_SPTR *ptrptr, BOOL *negptr, uint16_t *ptypeptr,+ uint16_t *pdataptr, int *errorcodeptr, compile_block *cb)+{+PCRE2_UCHAR c;+PCRE2_SIZE i, bot, top;+PCRE2_SPTR ptr = *ptrptr;+PCRE2_UCHAR name[32];++if (ptr >= cb->end_pattern) goto ERROR_RETURN;+c = *ptr++;+*negptr = FALSE;++/* \P or \p can be followed by a name in {}, optionally preceded by ^ for+negation. */++if (c == CHAR_LEFT_CURLY_BRACKET)+ {+ if (ptr >= cb->end_pattern) goto ERROR_RETURN;+ if (*ptr == CHAR_CIRCUMFLEX_ACCENT)+ {+ *negptr = TRUE;+ ptr++;+ }+ for (i = 0; i < (int)(sizeof(name) / sizeof(PCRE2_UCHAR)) - 1; i++)+ {+ if (ptr >= cb->end_pattern) goto ERROR_RETURN;+ c = *ptr++;+ if (c == CHAR_NUL) goto ERROR_RETURN;+ if (c == CHAR_RIGHT_CURLY_BRACKET) break;+ name[i] = c;+ }+ if (c != CHAR_RIGHT_CURLY_BRACKET) goto ERROR_RETURN;+ name[i] = 0;+ }++/* Otherwise there is just one following character, which must be an ASCII+letter. */++else if (MAX_255(c) && (cb->ctypes[c] & ctype_letter) != 0)+ {+ name[0] = c;+ name[1] = 0;+ }+else goto ERROR_RETURN;++*ptrptr = ptr;++/* Search for a recognized property name using binary chop. */++bot = 0;+top = PRIV(utt_size);++while (bot < top)+ {+ int r;+ i = (bot + top) >> 1;+ r = PRIV(strcmp_c8)(name, PRIV(utt_names) + PRIV(utt)[i].name_offset);+ if (r == 0)+ {+ *ptypeptr = PRIV(utt)[i].type;+ *pdataptr = PRIV(utt)[i].value;+ return TRUE;+ }+ if (r > 0) bot = i + 1; else top = i;+ }+*errorcodeptr = ERR47; /* Unrecognized name */+return FALSE;++ERROR_RETURN: /* Malformed \P or \p */+*errorcodeptr = ERR46;+*ptrptr = ptr;+return FALSE;+}+#endif++++/*************************************************+* Check for POSIX class syntax *+*************************************************/++/* This function is called when the sequence "[:" or "[." or "[=" is+encountered in a character class. It checks whether this is followed by a+sequence of characters terminated by a matching ":]" or ".]" or "=]". If we+reach an unescaped ']' without the special preceding character, return FALSE.++Originally, this function only recognized a sequence of letters between the+terminators, but it seems that Perl recognizes any sequence of characters,+though of course unknown POSIX names are subsequently rejected. Perl gives an+"Unknown POSIX class" error for [:f\oo:] for example, where previously PCRE+didn't consider this to be a POSIX class. Likewise for [:1234:].++The problem in trying to be exactly like Perl is in the handling of escapes. We+have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX+class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code+below handles the special cases \\ and \], but does not try to do any other+escape processing. This makes it different from Perl for cases such as+[:l\ower:] where Perl recognizes it as the POSIX class "lower" but PCRE does+not recognize "l\ower". This is a lesser evil than not diagnosing bad classes+when Perl does, I think.++A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not.+It seems that the appearance of a nested POSIX class supersedes an apparent+external class. For example, [:a[:digit:]b:] matches "a", "b", ":", or+a digit. This is handled by returning FALSE if the start of a new group with+the same terminator is encountered, since the next closing sequence must close+the nested group, not the outer one.++In Perl, unescaped square brackets may also appear as part of class names. For+example, [:a[:abc]b:] gives unknown POSIX class "[:abc]b:]". However, for+[:a[:abc]b][b:] it gives unknown POSIX class "[:abc]b][b:]", which does not+seem right at all. PCRE does not allow closing square brackets in POSIX class+names.++Arguments:+ ptr pointer to the character after the initial [ (colon, dot, equals)+ ptrend pointer to the end of the pattern+ endptr where to return a pointer to the terminating ':', '.', or '='++Returns: TRUE or FALSE+*/++static BOOL+check_posix_syntax(PCRE2_SPTR ptr, PCRE2_SPTR ptrend, PCRE2_SPTR *endptr)+{+PCRE2_UCHAR terminator; /* Don't combine these lines; the Solaris cc */+terminator = *ptr++; /* compiler warns about "non-constant" initializer. */++for (; ptrend - ptr >= 2; ptr++)+ {+ if (*ptr == CHAR_BACKSLASH &&+ (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET || ptr[1] == CHAR_BACKSLASH))+ ptr++;++ else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) ||+ *ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE;++ else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)+ {+ *endptr = ptr;+ return TRUE;+ }+ }++return FALSE;+}++++/*************************************************+* Check POSIX class name *+*************************************************/++/* This function is called to check the name given in a POSIX-style class entry+such as [:alnum:].++Arguments:+ ptr points to the first letter+ len the length of the name++Returns: a value representing the name, or -1 if unknown+*/++static int+check_posix_name(PCRE2_SPTR ptr, int len)+{+const char *pn = posix_names;+int yield = 0;+while (posix_name_lengths[yield] != 0)+ {+ if (len == posix_name_lengths[yield] &&+ PRIV(strncmp_c8)(ptr, pn, (unsigned int)len) == 0) return yield;+ pn += posix_name_lengths[yield] + 1;+ yield++;+ }+return -1;+}++++/*************************************************+* Read a subpattern or VERB name *+*************************************************/++/* This function is called from parse_regex() below whenever it needs to read+the name of a subpattern or a (*VERB) or an (*alpha_assertion). The initial+pointer must be to the character before the name. If that character is '*' we+are reading a verb or alpha assertion name. The pointer is updated to point+after the name, for a VERB or alpha assertion name, or after tha name's+terminator for a subpattern name. Returning both the offset and the name+pointer is redundant information, but some callers use one and some the other,+so it is simplest just to return both.++Arguments:+ ptrptr points to the character pointer variable+ ptrend points to the end of the input string+ utf true if the input is UTF-encoded+ terminator the terminator of a subpattern name must be this+ offsetptr where to put the offset from the start of the pattern+ nameptr where to put a pointer to the name in the input+ namelenptr where to put the length of the name+ errcodeptr where to put an error code+ cb pointer to the compile data block++Returns: TRUE if a name was read+ FALSE otherwise, with error code set+*/++static BOOL+read_name(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, BOOL utf, uint32_t terminator,+ PCRE2_SIZE *offsetptr, PCRE2_SPTR *nameptr, uint32_t *namelenptr,+ int *errorcodeptr, compile_block *cb)+{+PCRE2_SPTR ptr = *ptrptr;+BOOL is_group = (*ptr != CHAR_ASTERISK);++if (++ptr >= ptrend) /* No characters in name */+ {+ *errorcodeptr = is_group? ERR62: /* Subpattern name expected */+ ERR60; /* Verb not recognized or malformed */+ goto FAILED;+ }++*nameptr = ptr;+*offsetptr = (PCRE2_SIZE)(ptr - cb->start_pattern);++/* In UTF mode, a group name may contain letters and decimal digits as defined+by Unicode properties, and underscores, but must not start with a digit. */++#ifdef SUPPORT_UNICODE+if (utf && is_group)+ {+ uint32_t c, type;++ GETCHAR(c, ptr);+ type = UCD_CHARTYPE(c);++ if (type == ucp_Nd)+ {+ *errorcodeptr = ERR44;+ goto FAILED;+ }++ for(;;)+ {+ if (type != ucp_Nd && PRIV(ucp_gentype)[type] != ucp_L &&+ c != CHAR_UNDERSCORE) break;+ ptr++;+ FORWARDCHARTEST(ptr, ptrend);+ if (ptr >= ptrend) break;+ GETCHAR(c, ptr);+ type = UCD_CHARTYPE(c);+ }+ }+else+#else+(void)utf; /* Avoid compiler warning */+#endif /* SUPPORT_UNICODE */++/* Handle non-group names and group names in non-UTF modes. A group name must+not start with a digit. If either of the others start with a digit it just+won't be recognized. */++ {+ if (is_group && IS_DIGIT(*ptr))+ {+ *errorcodeptr = ERR44;+ goto FAILED;+ }++ while (ptr < ptrend && MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype_word) != 0)+ {+ ptr++;+ }+ }++/* Check name length */++if (ptr > *nameptr + MAX_NAME_SIZE)+ {+ *errorcodeptr = ERR48;+ goto FAILED;+ }+*namelenptr = (uint32_t)(ptr - *nameptr);++/* Subpattern names must not be empty, and their terminator is checked here.+(What follows a verb or alpha assertion name is checked separately.) */++if (is_group)+ {+ if (ptr == *nameptr)+ {+ *errorcodeptr = ERR62; /* Subpattern name expected */+ goto FAILED;+ }+ if (ptr >= ptrend || *ptr != (PCRE2_UCHAR)terminator)+ {+ *errorcodeptr = ERR42;+ goto FAILED;+ }+ ptr++;+ }++*ptrptr = ptr;+return TRUE;++FAILED:+*ptrptr = ptr;+return FALSE;+}++++/*************************************************+* Manage callouts at start of cycle *+*************************************************/++/* At the start of a new item in parse_regex() we are able to record the+details of the previous item in a prior callout, and also to set up an+automatic callout if enabled. Avoid having two adjacent automatic callouts,+which would otherwise happen for items such as \Q that contribute nothing to+the parsed pattern.++Arguments:+ ptr current pattern pointer+ pcalloutptr points to a pointer to previous callout, or NULL+ auto_callout TRUE if auto_callouts are enabled+ parsed_pattern the parsed pattern pointer+ cb compile block++Returns: possibly updated parsed_pattern pointer.+*/++static uint32_t *+manage_callouts(PCRE2_SPTR ptr, uint32_t **pcalloutptr, BOOL auto_callout,+ uint32_t *parsed_pattern, compile_block *cb)+{+uint32_t *previous_callout = *pcalloutptr;++if (previous_callout != NULL) previous_callout[2] = (uint32_t)(ptr -+ cb->start_pattern - (PCRE2_SIZE)previous_callout[1]);++if (!auto_callout) previous_callout = NULL; else+ {+ if (previous_callout == NULL ||+ previous_callout != parsed_pattern - 4 ||+ previous_callout[3] != 255)+ {+ previous_callout = parsed_pattern; /* Set up new automatic callout */+ parsed_pattern += 4;+ previous_callout[0] = META_CALLOUT_NUMBER;+ previous_callout[2] = 0;+ previous_callout[3] = 255;+ }+ previous_callout[1] = (uint32_t)(ptr - cb->start_pattern);+ }++*pcalloutptr = previous_callout;+return parsed_pattern;+}++++/*************************************************+* Parse regex and identify named groups *+*************************************************/++/* This function is called first of all. It scans the pattern and does two+things: (1) It identifies capturing groups and makes a table of named capturing+groups so that information about them is fully available to both the compiling+scans. (2) It writes a parsed version of the pattern with comments omitted and+escapes processed into the parsed_pattern vector.++Arguments:+ ptr points to the start of the pattern+ options compiling dynamic options (may change during the scan)+ has_lookbehind points to a boolean, set TRUE if a lookbehind is found+ cb pointer to the compile data block++Returns: zero on success or a non-zero error code, with the+ error offset placed in the cb field+*/++/* A structure and some flags for dealing with nested groups. */++typedef struct nest_save {+ uint16_t nest_depth;+ uint16_t reset_group;+ uint16_t max_group;+ uint16_t flags;+ uint32_t options;+} nest_save;++#define NSF_RESET 0x0001u+#define NSF_CONDASSERT 0x0002u+#define NSF_ATOMICSR 0x0004u++/* Options that are changeable within the pattern must be tracked during+parsing. Some (e.g. PCRE2_EXTENDED) are implemented entirely during parsing,+but all must be tracked so that META_OPTIONS items set the correct values for+the main compiling phase. */++#define PARSE_TRACKED_OPTIONS (PCRE2_CASELESS|PCRE2_DOTALL|PCRE2_DUPNAMES| \+ PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_MULTILINE|PCRE2_NO_AUTO_CAPTURE| \+ PCRE2_UNGREEDY)++/* States used for analyzing ranges in character classes. The two OK values+must be last. */++enum { RANGE_NO, RANGE_STARTED, RANGE_OK_ESCAPED, RANGE_OK_LITERAL };++/* Only in 32-bit mode can there be literals > META_END. A macro encapsulates+the storing of literal values in the main parsed pattern, where they can always+be quantified. */++#if PCRE2_CODE_UNIT_WIDTH == 32+#define PARSED_LITERAL(c, p) \+ { \+ if (c >= META_END) *p++ = META_BIGVALUE; \+ *p++ = c; \+ okquantifier = TRUE; \+ }+#else+#define PARSED_LITERAL(c, p) *p++ = c; okquantifier = TRUE;+#endif++/* Here's the actual function. */++static int parse_regex(PCRE2_SPTR ptr, uint32_t options, BOOL *has_lookbehind,+ compile_block *cb)+{+uint32_t c;+uint32_t delimiter;+uint32_t namelen;+uint32_t class_range_state;+uint32_t *verblengthptr = NULL; /* Value avoids compiler warning */+uint32_t *verbstartptr = NULL;+uint32_t *previous_callout = NULL;+uint32_t *parsed_pattern = cb->parsed_pattern;+uint32_t *parsed_pattern_end = cb->parsed_pattern_end;+uint32_t meta_quantifier = 0;+uint32_t add_after_mark = 0;+uint32_t extra_options = cb->cx->extra_options;+uint16_t nest_depth = 0;+int after_manual_callout = 0;+int expect_cond_assert = 0;+int errorcode = 0;+int escape;+int i;+BOOL inescq = FALSE;+BOOL inverbname = FALSE;+BOOL utf = (options & PCRE2_UTF) != 0;+BOOL auto_callout = (options & PCRE2_AUTO_CALLOUT) != 0;+BOOL isdupname;+BOOL negate_class;+BOOL okquantifier = FALSE;+PCRE2_SPTR thisptr;+PCRE2_SPTR name;+PCRE2_SPTR ptrend = cb->end_pattern;+PCRE2_SPTR verbnamestart = NULL; /* Value avoids compiler warning */+named_group *ng;+nest_save *top_nest, *end_nests;++/* Insert leading items for word and line matching (features provided for the+benefit of pcre2grep). */++if ((extra_options & PCRE2_EXTRA_MATCH_LINE) != 0)+ {+ *parsed_pattern++ = META_CIRCUMFLEX;+ *parsed_pattern++ = META_NOCAPTURE;+ }+else if ((extra_options & PCRE2_EXTRA_MATCH_WORD) != 0)+ {+ *parsed_pattern++ = META_ESCAPE + ESC_b;+ *parsed_pattern++ = META_NOCAPTURE;+ }++/* If the pattern is actually a literal string, process it separately to avoid+cluttering up the main loop. */++if ((options & PCRE2_LITERAL) != 0)+ {+ while (ptr < ptrend)+ {+ if (parsed_pattern >= parsed_pattern_end)+ {+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */+ goto FAILED;+ }+ thisptr = ptr;+ GETCHARINCTEST(c, ptr);+ if (auto_callout)+ parsed_pattern = manage_callouts(thisptr, &previous_callout,+ auto_callout, parsed_pattern, cb);+ PARSED_LITERAL(c, parsed_pattern);+ }+ goto PARSED_END;+ }++/* Process a real regex which may contain meta-characters. */++top_nest = NULL;+end_nests = (nest_save *)(cb->start_workspace + cb->workspace_size);++/* The size of the nest_save structure might not be a factor of the size of the+workspace. Therefore we must round down end_nests so as to correctly avoid+creating a nest_save that spans the end of the workspace. */++end_nests = (nest_save *)((char *)end_nests -+ ((cb->workspace_size * sizeof(PCRE2_UCHAR)) % sizeof(nest_save)));++/* PCRE2_EXTENDED_MORE implies PCRE2_EXTENDED */++if ((options & PCRE2_EXTENDED_MORE) != 0) options |= PCRE2_EXTENDED;++/* Now scan the pattern */++while (ptr < ptrend)+ {+ int prev_expect_cond_assert;+ uint32_t min_repeat, max_repeat;+ uint32_t set, unset, *optset;+ uint32_t terminator;+ uint32_t prev_meta_quantifier;+ BOOL prev_okquantifier;+ PCRE2_SPTR tempptr;+ PCRE2_SIZE offset;++ if (parsed_pattern >= parsed_pattern_end)+ {+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */+ goto FAILED;+ }++ if (nest_depth > cb->cx->parens_nest_limit)+ {+ errorcode = ERR19;+ goto FAILED; /* Parentheses too deeply nested */+ }++ /* Get next input character, save its position for callout handling. */++ thisptr = ptr;+ GETCHARINCTEST(c, ptr);++ /* Copy quoted literals until \E, allowing for the possibility of automatic+ callouts, except when processing a (*VERB) "name". */++ if (inescq)+ {+ if (c == CHAR_BACKSLASH && ptr < ptrend && *ptr == CHAR_E)+ {+ inescq = FALSE;+ ptr++; /* Skip E */+ }+ else+ {+ if (expect_cond_assert > 0) /* A literal is not allowed if we are */+ { /* expecting a conditional assertion, */+ ptr--; /* but an empty \Q\E sequence is OK. */+ errorcode = ERR28;+ goto FAILED;+ }+ if (inverbname)+ { /* Don't use PARSED_LITERAL() because it */+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;+#endif+ *parsed_pattern++ = c;+ }+ else+ {+ if (after_manual_callout-- <= 0)+ parsed_pattern = manage_callouts(thisptr, &previous_callout,+ auto_callout, parsed_pattern, cb);+ PARSED_LITERAL(c, parsed_pattern);+ }+ meta_quantifier = 0;+ }+ continue; /* Next character */+ }++ /* If we are processing the "name" part of a (*VERB:NAME) item, all+ characters up to the closing parenthesis are literals except when+ PCRE2_ALT_VERBNAMES is set. That causes backslash interpretation, but only \Q+ and \E and escaped characters are allowed (no character types such as \d). If+ PCRE2_EXTENDED is also set, we must ignore white space and # comments. Do+ this by not entering the special (*VERB:NAME) processing - they are then+ picked up below. Note that c is a character, not a code unit, so we must not+ use MAX_255 to test its size because MAX_255 tests code units and is assumed+ TRUE in 8-bit mode. */++ if (inverbname &&+ (+ /* EITHER: not both options set */+ ((options & (PCRE2_EXTENDED | PCRE2_ALT_VERBNAMES)) !=+ (PCRE2_EXTENDED | PCRE2_ALT_VERBNAMES)) ||+#ifdef SUPPORT_UNICODE+ /* OR: character > 255 AND not Unicode Pattern White Space */+ (c > 255 && (c|1) != 0x200f && (c|1) != 0x2029) ||+#endif+ /* OR: not a # comment or isspace() white space */+ (c < 256 && c != CHAR_NUMBER_SIGN && (cb->ctypes[c] & ctype_space) == 0+#ifdef SUPPORT_UNICODE+ /* and not CHAR_NEL when Unicode is supported */+ && c != CHAR_NEL+#endif+ )))+ {+ PCRE2_SIZE verbnamelength;++ switch(c)+ {+ default: /* Don't use PARSED_LITERAL() because it */+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;+#endif+ *parsed_pattern++ = c;+ break;++ case CHAR_RIGHT_PARENTHESIS:+ inverbname = FALSE;+ /* This is the length in characters */+ verbnamelength = (PCRE2_SIZE)(parsed_pattern - verblengthptr - 1);+ /* But the limit on the length is in code units */+ if (ptr - verbnamestart - 1 > (int)MAX_MARK)+ {+ ptr--;+ errorcode = ERR76;+ goto FAILED;+ }+ *verblengthptr = (uint32_t)verbnamelength;++ /* If this name was on a verb such as (*ACCEPT) which does not continue,+ a (*MARK) was generated for the name. We now add the original verb as the+ next item. */++ if (add_after_mark != 0)+ {+ *parsed_pattern++ = add_after_mark;+ add_after_mark = 0;+ }+ break;++ case CHAR_BACKSLASH:+ if ((options & PCRE2_ALT_VERBNAMES) != 0)+ {+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,+ cb->cx->extra_options, FALSE, cb);+ if (errorcode != 0) goto FAILED;+ }+ else escape = 0; /* Treat all as literal */++ switch(escape)+ {+ case 0: /* Don't use PARSED_LITERAL() because it */+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;+#endif+ *parsed_pattern++ = c;+ break;++ case ESC_Q:+ inescq = TRUE;+ break;++ case ESC_E: /* Ignore */+ break;++ default:+ errorcode = ERR40; /* Invalid in verb name */+ goto FAILED;+ }+ }+ continue; /* Next character in pattern */+ }++ /* Not a verb name character. At this point we must process everything that+ must not change the quantification state. This is mainly comments, but we+ handle \Q and \E here as well, so that an item such as A\Q\E+ is treated as+ A+, as in Perl. An isolated \E is ignored. */++ if (c == CHAR_BACKSLASH && ptr < ptrend)+ {+ if (*ptr == CHAR_Q || *ptr == CHAR_E)+ {+ inescq = *ptr == CHAR_Q;+ ptr++;+ continue;+ }+ }++ /* Skip over whitespace and # comments in extended mode. Note that c is a+ character, not a code unit, so we must not use MAX_255 to test its size+ because MAX_255 tests code units and is assumed TRUE in 8-bit mode. The+ whitespace characters are those designated as "Pattern White Space" by+ Unicode, which are the isspace() characters plus CHAR_NEL (newline), which is+ U+0085 in Unicode, plus U+200E, U+200F, U+2028, and U+2029. These are a+ subset of space characters that match \h and \v. */++ if ((options & PCRE2_EXTENDED) != 0)+ {+ if (c < 256 && (cb->ctypes[c] & ctype_space) != 0) continue;+#ifdef SUPPORT_UNICODE+ if (c == CHAR_NEL || (c|1) == 0x200f || (c|1) == 0x2029) continue;+#endif+ if (c == CHAR_NUMBER_SIGN)+ {+ while (ptr < ptrend)+ {+ if (IS_NEWLINE(ptr)) /* For non-fixed-length newline cases, */+ { /* IS_NEWLINE sets cb->nllen. */+ ptr += cb->nllen;+ break;+ }+ ptr++;+#ifdef SUPPORT_UNICODE+ if (utf) FORWARDCHARTEST(ptr, ptrend);+#endif+ }+ continue; /* Next character in pattern */+ }+ }++ /* Skip over bracketed comments */++ if (c == CHAR_LEFT_PARENTHESIS && ptrend - ptr >= 2 &&+ ptr[0] == CHAR_QUESTION_MARK && ptr[1] == CHAR_NUMBER_SIGN)+ {+ while (++ptr < ptrend && *ptr != CHAR_RIGHT_PARENTHESIS);+ if (ptr >= ptrend)+ {+ errorcode = ERR18; /* A special error for missing ) in a comment */+ goto FAILED; /* to make it easier to debug. */+ }+ ptr++;+ continue; /* Next character in pattern */+ }++ /* If the next item is not a quantifier, fill in length of any previous+ callout and create an auto callout if required. */++ if (c != CHAR_ASTERISK && c != CHAR_PLUS && c != CHAR_QUESTION_MARK &&+ (c != CHAR_LEFT_CURLY_BRACKET ||+ (tempptr = ptr,+ !read_repeat_counts(&tempptr, ptrend, NULL, NULL, &errorcode))))+ {+ if (after_manual_callout-- <= 0)+ parsed_pattern = manage_callouts(thisptr, &previous_callout, auto_callout,+ parsed_pattern, cb);+ }++ /* If expect_cond_assert is 2, we have just passed (?( and are expecting an+ assertion, possibly preceded by a callout. If the value is 1, we have just+ had the callout and expect an assertion. There must be at least 3 more+ characters in all cases. When expect_cond_assert is 2, we know that the+ current character is an opening parenthesis, as otherwise we wouldn't be+ here. However, when it is 1, we need to check, and it's easiest just to check+ always. Note that expect_cond_assert may be negative, since all callouts just+ decrement it. */++ if (expect_cond_assert > 0)+ {+ BOOL ok = c == CHAR_LEFT_PARENTHESIS && ptrend - ptr >= 3 &&+ (ptr[0] == CHAR_QUESTION_MARK || ptr[0] == CHAR_ASTERISK);+ if (ok)+ {+ if (ptr[0] == CHAR_ASTERISK) /* New alpha assertion format, possibly */+ {+ ok = MAX_255(ptr[1]) && (cb->ctypes[ptr[1]] & ctype_lcletter) != 0;+ }+ else switch(ptr[1]) /* Traditional symbolic format */+ {+ case CHAR_C:+ ok = expect_cond_assert == 2;+ break;++ case CHAR_EQUALS_SIGN:+ case CHAR_EXCLAMATION_MARK:+ break;++ case CHAR_LESS_THAN_SIGN:+ ok = ptr[2] == CHAR_EQUALS_SIGN || ptr[2] == CHAR_EXCLAMATION_MARK;+ break;++ default:+ ok = FALSE;+ }+ }++ if (!ok)+ {+ ptr--; /* Adjust error offset */+ errorcode = ERR28;+ goto FAILED;+ }+ }++ /* Remember whether we are expecting a conditional assertion, and set the+ default for this item. */++ prev_expect_cond_assert = expect_cond_assert;+ expect_cond_assert = 0;++ /* Remember quantification status for the previous significant item, then set+ default for this item. */++ prev_okquantifier = okquantifier;+ prev_meta_quantifier = meta_quantifier;+ okquantifier = FALSE;+ meta_quantifier = 0;++ /* If the previous significant item was a quantifier, adjust the parsed code+ if there is a following modifier. The base meta value is always followed by+ the PLUS and QUERY values, in that order. We do this here rather than after+ reading a quantifier so that intervening comments and /x whitespace can be+ ignored without having to replicate code. */++ if (prev_meta_quantifier != 0 && (c == CHAR_QUESTION_MARK || c == CHAR_PLUS))+ {+ parsed_pattern[(prev_meta_quantifier == META_MINMAX)? -3 : -1] =+ prev_meta_quantifier + ((c == CHAR_QUESTION_MARK)?+ 0x00020000u : 0x00010000u);+ continue; /* Next character in pattern */+ }+++ /* Process the next item in the main part of a pattern. */++ switch(c)+ {+ default: /* Non-special character */+ PARSED_LITERAL(c, parsed_pattern);+ break;+++ /* ---- Escape sequence ---- */++ case CHAR_BACKSLASH:+ tempptr = ptr;+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,+ cb->cx->extra_options, FALSE, cb);+ if (errorcode != 0)+ {+ ESCAPE_FAILED:+ if ((extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)+ goto FAILED;+ ptr = tempptr;+ if (ptr >= ptrend) c = CHAR_BACKSLASH; else+ {+ GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */+ }+ escape = 0; /* Treat as literal character */+ }++ /* The escape was a data escape or literal character. */++ if (escape == 0)+ {+ PARSED_LITERAL(c, parsed_pattern);+ }++ /* The escape was a back (or forward) reference. We keep the offset in+ order to give a more useful diagnostic for a bad forward reference. For+ references to groups numbered less than 10 we can't use more than two items+ in parsed_pattern because they may be just two characters in the input (and+ in a 64-bit world an offset may need two elements). So for them, the offset+ of the first occurrent is held in a special vector. */++ else if (escape < 0)+ {+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 1);+ escape = -escape;+ *parsed_pattern++ = META_BACKREF | (uint32_t)escape;+ if (escape < 10)+ {+ if (cb->small_ref_offset[escape] == PCRE2_UNSET)+ cb->small_ref_offset[escape] = offset;+ }+ else+ {+ PUTOFFSET(offset, parsed_pattern);+ }+ okquantifier = TRUE;+ }++ /* The escape was a character class such as \d etc. or other special+ escape indicator such as \A or \X. Most of them generate just a single+ parsed item, but \P and \p are followed by a 16-bit type and a 16-bit+ value. They are supported only when Unicode is available. The type and+ value are packed into a single 32-bit value so that the whole sequences+ uses only two elements in the parsed_vector. This is because the same+ coding is used if \d (for example) is turned into \p{Nd} when PCRE2_UCP is+ set.++ There are also some cases where the escape sequence is followed by a name:+ \k{name}, \k<name>, and \k'name' are backreferences by name, and \g<name>+ and \g'name' are subroutine calls by name; \g{name} is a synonym for+ \k{name}. Note that \g<number> and \g'number' are handled by check_escape()+ and returned as a negative value (handled above). A name is coded as an+ offset into the pattern and a length. */++ else switch (escape)+ {+ case ESC_C:+#ifdef NEVER_BACKSLASH_C+ errorcode = ERR85;+ goto ESCAPE_FAILED;+#else+ if ((options & PCRE2_NEVER_BACKSLASH_C) != 0)+ {+ errorcode = ERR83;+ goto ESCAPE_FAILED;+ }+#endif+ okquantifier = TRUE;+ *parsed_pattern++ = META_ESCAPE + escape;+ break;++ case ESC_X:+#ifndef SUPPORT_UNICODE+ errorcode = ERR45; /* Supported only with Unicode support */+ goto ESCAPE_FAILED;+#endif+ case ESC_H:+ case ESC_h:+ case ESC_N:+ case ESC_R:+ case ESC_V:+ case ESC_v:+ okquantifier = TRUE;+ *parsed_pattern++ = META_ESCAPE + escape;+ break;++ default: /* \A, \B, \b, \G, \K, \Z, \z cannot be quantified. */+ *parsed_pattern++ = META_ESCAPE + escape;+ break;++ /* Escapes that change in UCP mode. Note that PCRE2_UCP will never be set+ without Unicode support because it is checked when pcre2_compile() is+ called. */++ case ESC_d:+ case ESC_D:+ case ESC_s:+ case ESC_S:+ case ESC_w:+ case ESC_W:+ okquantifier = TRUE;+ if ((options & PCRE2_UCP) == 0)+ {+ *parsed_pattern++ = META_ESCAPE + escape;+ }+ else+ {+ *parsed_pattern++ = META_ESCAPE ++ ((escape == ESC_d || escape == ESC_s || escape == ESC_w)?+ ESC_p : ESC_P);+ switch(escape)+ {+ case ESC_d:+ case ESC_D:+ *parsed_pattern++ = (PT_PC << 16) | ucp_Nd;+ break;++ case ESC_s:+ case ESC_S:+ *parsed_pattern++ = PT_SPACE << 16;+ break;++ case ESC_w:+ case ESC_W:+ *parsed_pattern++ = PT_WORD << 16;+ break;+ }+ }+ break;++ /* Unicode property matching */++ case ESC_P:+ case ESC_p:+#ifdef SUPPORT_UNICODE+ {+ BOOL negated;+ uint16_t ptype = 0, pdata = 0;+ if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb))+ goto ESCAPE_FAILED;+ if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P;+ *parsed_pattern++ = META_ESCAPE + escape;+ *parsed_pattern++ = (ptype << 16) | pdata;+ okquantifier = TRUE;+ }+#else+ errorcode = ERR45;+ goto ESCAPE_FAILED;+#endif+ break; /* End \P and \p */++ /* When \g is used with quotes or angle brackets as delimiters, it is a+ numerical or named subroutine call, and control comes here. When used+ with brace delimiters it is a numberical back reference and does not come+ here because check_escape() returns it directly as a reference. \k is+ always a named back reference. */++ case ESC_g:+ case ESC_k:+ if (ptr >= ptrend || (*ptr != CHAR_LEFT_CURLY_BRACKET &&+ *ptr != CHAR_LESS_THAN_SIGN && *ptr != CHAR_APOSTROPHE))+ {+ errorcode = (escape == ESC_g)? ERR57 : ERR69;+ goto ESCAPE_FAILED;+ }+ terminator = (*ptr == CHAR_LESS_THAN_SIGN)?+ CHAR_GREATER_THAN_SIGN : (*ptr == CHAR_APOSTROPHE)?+ CHAR_APOSTROPHE : CHAR_RIGHT_CURLY_BRACKET;++ /* For a non-braced \g, check for a numerical recursion. */++ if (escape == ESC_g && terminator != CHAR_RIGHT_CURLY_BRACKET)+ {+ PCRE2_SPTR p = ptr + 1;++ if (read_number(&p, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &i,+ &errorcode))+ {+ if (p >= ptrend || *p != terminator)+ {+ errorcode = ERR57;+ goto ESCAPE_FAILED;+ }+ ptr = p;+ goto SET_RECURSION;+ }+ if (errorcode != 0) goto ESCAPE_FAILED;+ }++ /* Not a numerical recursion */++ if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,+ &errorcode, cb)) goto ESCAPE_FAILED;++ /* \k and \g when used with braces are back references, whereas \g used+ with quotes or angle brackets is a recursion */++ *parsed_pattern++ =+ (escape == ESC_k || terminator == CHAR_RIGHT_CURLY_BRACKET)?+ META_BACKREF_BYNAME : META_RECURSE_BYNAME;+ *parsed_pattern++ = namelen;++ PUTOFFSET(offset, parsed_pattern);+ okquantifier = TRUE;+ break; /* End special escape processing */+ }+ break; /* End escape sequence processing */+++ /* ---- Single-character special items ---- */++ case CHAR_CIRCUMFLEX_ACCENT:+ *parsed_pattern++ = META_CIRCUMFLEX;+ break;++ case CHAR_DOLLAR_SIGN:+ *parsed_pattern++ = META_DOLLAR;+ break;++ case CHAR_DOT:+ *parsed_pattern++ = META_DOT;+ okquantifier = TRUE;+ break;+++ /* ---- Single-character quantifiers ---- */++ case CHAR_ASTERISK:+ meta_quantifier = META_ASTERISK;+ goto CHECK_QUANTIFIER;++ case CHAR_PLUS:+ meta_quantifier = META_PLUS;+ goto CHECK_QUANTIFIER;++ case CHAR_QUESTION_MARK:+ meta_quantifier = META_QUERY;+ goto CHECK_QUANTIFIER;+++ /* ---- Potential {n,m} quantifier ---- */++ case CHAR_LEFT_CURLY_BRACKET:+ if (!read_repeat_counts(&ptr, ptrend, &min_repeat, &max_repeat,+ &errorcode))+ {+ if (errorcode != 0) goto FAILED; /* Error in quantifier. */+ PARSED_LITERAL(c, parsed_pattern); /* Not a quantifier */+ break; /* No more quantifier processing */+ }+ meta_quantifier = META_MINMAX;+ /* Fall through */+++ /* ---- Quantifier post-processing ---- */++ /* Check that a quantifier is allowed after the previous item. */++ CHECK_QUANTIFIER:+ if (!prev_okquantifier)+ {+ errorcode = ERR9;+ goto FAILED_BACK;+ }++ /* Most (*VERB)s are not allowed to be quantified, but an ungreedy+ quantifier can be useful for (*ACCEPT) - meaning "succeed on backtrack", a+ sort of negated (*COMMIT). We therefore allow (*ACCEPT) to be quantified by+ wrapping it in non-capturing brackets, but we have to allow for a preceding+ (*MARK) for when (*ACCEPT) has an argument. */++ if (parsed_pattern[-1] == META_ACCEPT)+ {+ uint32_t *p;+ for (p = parsed_pattern - 1; p >= verbstartptr; p--) p[1] = p[0];+ *verbstartptr = META_NOCAPTURE;+ parsed_pattern[1] = META_KET;+ parsed_pattern += 2;+ }++ /* Now we can put the quantifier into the parsed pattern vector. At this+ stage, we have only the basic quantifier. The check for a following + or ?+ modifier happens at the top of the loop, after any intervening comments+ have been removed. */++ *parsed_pattern++ = meta_quantifier;+ if (c == CHAR_LEFT_CURLY_BRACKET)+ {+ *parsed_pattern++ = min_repeat;+ *parsed_pattern++ = max_repeat;+ }+ break;+++ /* ---- Character class ---- */++ case CHAR_LEFT_SQUARE_BRACKET:+ okquantifier = TRUE;++ /* In another (POSIX) regex library, the ugly syntax [[:<:]] and [[:>:]] is+ used for "start of word" and "end of word". As these are otherwise illegal+ sequences, we don't break anything by recognizing them. They are replaced+ by \b(?=\w) and \b(?<=\w) respectively. Sequences like [a[:<:]] are+ erroneous and are handled by the normal code below. */++ if (ptrend - ptr >= 6 &&+ (PRIV(strncmp_c8)(ptr, STRING_WEIRD_STARTWORD, 6) == 0 ||+ PRIV(strncmp_c8)(ptr, STRING_WEIRD_ENDWORD, 6) == 0))+ {+ *parsed_pattern++ = META_ESCAPE + ESC_b;++ if (ptr[2] == CHAR_LESS_THAN_SIGN)+ {+ *parsed_pattern++ = META_LOOKAHEAD;+ }+ else+ {+ *parsed_pattern++ = META_LOOKBEHIND;+ *has_lookbehind = TRUE;++ /* The offset is used only for the "non-fixed length" error; this won't+ occur here, so just store zero. */++ PUTOFFSET((PCRE2_SIZE)0, parsed_pattern);+ }++ if ((options & PCRE2_UCP) == 0)+ *parsed_pattern++ = META_ESCAPE + ESC_w;+ else+ {+ *parsed_pattern++ = META_ESCAPE + ESC_p;+ *parsed_pattern++ = PT_WORD << 16;+ }+ *parsed_pattern++ = META_KET;+ ptr += 6;+ break;+ }++ /* PCRE supports POSIX class stuff inside a class. Perl gives an error if+ they are encountered at the top level, so we'll do that too. */++ if (ptr < ptrend && (*ptr == CHAR_COLON || *ptr == CHAR_DOT ||+ *ptr == CHAR_EQUALS_SIGN) &&+ check_posix_syntax(ptr, ptrend, &tempptr))+ {+ errorcode = (*ptr-- == CHAR_COLON)? ERR12 : ERR13;+ goto FAILED;+ }++ /* Process a regular character class. If the first character is '^', set+ the negation flag. If the first few characters (either before or after ^)+ are \Q\E or \E or space or tab in extended-more mode, we skip them too.+ This makes for compatibility with Perl. */++ negate_class = FALSE;+ while (ptr < ptrend)+ {+ GETCHARINCTEST(c, ptr);+ if (c == CHAR_BACKSLASH)+ {+ if (ptr < ptrend && *ptr == CHAR_E) ptr++;+ else if (ptrend - ptr >= 3 &&+ PRIV(strncmp_c8)(ptr, STR_Q STR_BACKSLASH STR_E, 3) == 0)+ ptr += 3;+ else+ break;+ }+ else if ((options & PCRE2_EXTENDED_MORE) != 0 &&+ (c == CHAR_SPACE || c == CHAR_HT)) /* Note: just these two */+ continue;+ else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT)+ negate_class = TRUE;+ else break;+ }++ /* Now the real contents of the class; c has the first "real" character.+ Empty classes are permitted only if the option is set. */++ if (c == CHAR_RIGHT_SQUARE_BRACKET &&+ (cb->external_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)+ {+ *parsed_pattern++ = negate_class? META_CLASS_EMPTY_NOT : META_CLASS_EMPTY;+ break; /* End of class processing */+ }++ /* Process a non-empty class. */++ *parsed_pattern++ = negate_class? META_CLASS_NOT : META_CLASS;+ class_range_state = RANGE_NO;++ /* In an EBCDIC environment, Perl treats alphabetic ranges specially+ because there are holes in the encoding, and simply using the range A-Z+ (for example) would include the characters in the holes. This applies only+ to ranges where both values are literal; [\xC1-\xE9] is different to [A-Z]+ in this respect. In order to accommodate this, we keep track of whether+ character values are literal or not, and a state variable for handling+ ranges. */++ /* Loop for the contents of the class */++ for (;;)+ {+ BOOL char_is_literal = TRUE;++ /* Inside \Q...\E everything is literal except \E */++ if (inescq)+ {+ if (c == CHAR_BACKSLASH && ptr < ptrend && *ptr == CHAR_E)+ {+ inescq = FALSE; /* Reset literal state */+ ptr++; /* Skip the 'E' */+ goto CLASS_CONTINUE;+ }+ goto CLASS_LITERAL;+ }++ /* Skip over space and tab (only) in extended-more mode. */++ if ((options & PCRE2_EXTENDED_MORE) != 0 &&+ (c == CHAR_SPACE || c == CHAR_HT))+ goto CLASS_CONTINUE;++ /* Handle POSIX class names. Perl allows a negation extension of the+ form [:^name:]. A square bracket that doesn't match the syntax is+ treated as a literal. We also recognize the POSIX constructions+ [.ch.] and [=ch=] ("collating elements") and fault them, as Perl+ 5.6 and 5.8 do. */++ if (c == CHAR_LEFT_SQUARE_BRACKET &&+ ptrend - ptr >= 3 &&+ (*ptr == CHAR_COLON || *ptr == CHAR_DOT ||+ *ptr == CHAR_EQUALS_SIGN) &&+ check_posix_syntax(ptr, ptrend, &tempptr))+ {+ BOOL posix_negate = FALSE;+ int posix_class;++ /* Perl treats a hyphen before a POSIX class as a literal, not the+ start of a range. However, it gives a warning in its warning mode. PCRE+ does not have a warning mode, so we give an error, because this is+ likely an error on the user's part. */++ if (class_range_state == RANGE_STARTED)+ {+ errorcode = ERR50;+ goto FAILED;+ }++ if (*ptr != CHAR_COLON)+ {+ errorcode = ERR13;+ goto FAILED_BACK;+ }++ if (*(++ptr) == CHAR_CIRCUMFLEX_ACCENT)+ {+ posix_negate = TRUE;+ ptr++;+ }++ posix_class = check_posix_name(ptr, (int)(tempptr - ptr));+ if (posix_class < 0)+ {+ errorcode = ERR30;+ goto FAILED;+ }+ ptr = tempptr + 2;++ /* Perl treats a hyphen after a POSIX class as a literal, not the+ start of a range. However, it gives a warning in its warning mode+ unless the hyphen is the last character in the class. PCRE does not+ have a warning mode, so we give an error, because this is likely an+ error on the user's part. */++ if (ptr < ptrend - 1 && *ptr == CHAR_MINUS &&+ ptr[1] != CHAR_RIGHT_SQUARE_BRACKET)+ {+ errorcode = ERR50;+ goto FAILED;+ }++ /* Set "a hyphen is not the start of a range" for the -] case, and also+ in case the POSIX class is followed by \E or \Q\E (possibly repeated -+ fuzzers do that kind of thing) and *then* a hyphen. This causes that+ hyphen to be treated as a literal. I don't think it's worth setting up+ special apparatus to do otherwise. */++ class_range_state = RANGE_NO;++ /* When PCRE2_UCP is set, some of the POSIX classes are converted to+ use Unicode properties \p or \P or, in one case, \h or \H. The+ substitutes table has two values per class, containing the type and+ value of a \p or \P item. The special cases are specified with a+ negative type: a non-zero value causes \h or \H to be used, and a zero+ value falls through to behave like a non-UCP POSIX class. */++#ifdef SUPPORT_UNICODE+ if ((options & PCRE2_UCP) != 0)+ {+ int ptype = posix_substitutes[2*posix_class];+ int pvalue = posix_substitutes[2*posix_class + 1];+ if (ptype >= 0)+ {+ *parsed_pattern++ = META_ESCAPE + (posix_negate? ESC_P : ESC_p);+ *parsed_pattern++ = (ptype << 16) | pvalue;+ goto CLASS_CONTINUE;+ }++ if (pvalue != 0)+ {+ *parsed_pattern++ = META_ESCAPE + (posix_negate? ESC_H : ESC_h);+ goto CLASS_CONTINUE;+ }++ /* Fall through */+ }+#endif /* SUPPORT_UNICODE */++ /* Non-UCP POSIX class */++ *parsed_pattern++ = posix_negate? META_POSIX_NEG : META_POSIX;+ *parsed_pattern++ = posix_class;+ }++ /* Handle potential start of range */++ else if (c == CHAR_MINUS && class_range_state >= RANGE_OK_ESCAPED)+ {+ *parsed_pattern++ = (class_range_state == RANGE_OK_LITERAL)?+ META_RANGE_LITERAL : META_RANGE_ESCAPED;+ class_range_state = RANGE_STARTED;+ }++ /* Handle a literal character */++ else if (c != CHAR_BACKSLASH)+ {+ CLASS_LITERAL:+ if (class_range_state == RANGE_STARTED)+ {+ if (c == parsed_pattern[-2]) /* Optimize one-char range */+ parsed_pattern--;+ else if (parsed_pattern[-2] > c) /* Check range is in order */+ {+ errorcode = ERR8;+ goto FAILED_BACK;+ }+ else+ {+ if (!char_is_literal && parsed_pattern[-1] == META_RANGE_LITERAL)+ parsed_pattern[-1] = META_RANGE_ESCAPED;+ PARSED_LITERAL(c, parsed_pattern);+ }+ class_range_state = RANGE_NO;+ }+ else /* Potential start of range */+ {+ class_range_state = char_is_literal?+ RANGE_OK_LITERAL : RANGE_OK_ESCAPED;+ PARSED_LITERAL(c, parsed_pattern);+ }+ }++ /* Handle escapes in a class */++ else+ {+ tempptr = ptr;+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,+ cb->cx->extra_options, TRUE, cb);++ if (errorcode != 0)+ {+ if ((extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)+ goto FAILED;+ ptr = tempptr;+ if (ptr >= ptrend) c = CHAR_BACKSLASH; else+ {+ GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */+ }+ escape = 0; /* Treat as literal character */+ }++ switch(escape)+ {+ case 0: /* Escaped character code point is in c */+ char_is_literal = FALSE;+ goto CLASS_LITERAL;++ case ESC_b:+ c = CHAR_BS; /* \b is backspace in a class */+ char_is_literal = FALSE;+ goto CLASS_LITERAL;++ case ESC_Q:+ inescq = TRUE; /* Enter literal mode */+ goto CLASS_CONTINUE;++ case ESC_E: /* Ignore orphan \E */+ goto CLASS_CONTINUE;++ case ESC_B: /* Always an error in a class */+ case ESC_R:+ case ESC_X:+ errorcode = ERR7;+ ptr--;+ goto FAILED;+ }++ /* The second part of a range can be a single-character escape+ sequence (detected above), but not any of the other escapes. Perl+ treats a hyphen as a literal in such circumstances. However, in Perl's+ warning mode, a warning is given, so PCRE now faults it, as it is+ almost certainly a mistake on the user's part. */++ if (class_range_state == RANGE_STARTED)+ {+ errorcode = ERR50;+ goto FAILED; /* Not CLASS_ESCAPE_FAILED; always an error */+ }++ /* Of the remaining escapes, only those that define characters are+ allowed in a class. None may start a range. */++ class_range_state = RANGE_NO;+ switch(escape)+ {+ case ESC_N:+ errorcode = ERR71;+ goto FAILED;++ case ESC_H:+ case ESC_h:+ case ESC_V:+ case ESC_v:+ *parsed_pattern++ = META_ESCAPE + escape;+ break;++ /* These escapes are converted to Unicode property tests when+ PCRE2_UCP is set. */++ case ESC_d:+ case ESC_D:+ case ESC_s:+ case ESC_S:+ case ESC_w:+ case ESC_W:+ if ((options & PCRE2_UCP) == 0)+ {+ *parsed_pattern++ = META_ESCAPE + escape;+ }+ else+ {+ *parsed_pattern++ = META_ESCAPE ++ ((escape == ESC_d || escape == ESC_s || escape == ESC_w)?+ ESC_p : ESC_P);+ switch(escape)+ {+ case ESC_d:+ case ESC_D:+ *parsed_pattern++ = (PT_PC << 16) | ucp_Nd;+ break;++ case ESC_s:+ case ESC_S:+ *parsed_pattern++ = PT_SPACE << 16;+ break;++ case ESC_w:+ case ESC_W:+ *parsed_pattern++ = PT_WORD << 16;+ break;+ }+ }+ break;++ /* Explicit Unicode property matching */++ case ESC_P:+ case ESC_p:+#ifdef SUPPORT_UNICODE+ {+ BOOL negated;+ uint16_t ptype = 0, pdata = 0;+ if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb))+ goto FAILED;+ if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P;+ *parsed_pattern++ = META_ESCAPE + escape;+ *parsed_pattern++ = (ptype << 16) | pdata;+ }+#else+ errorcode = ERR45;+ goto FAILED;+#endif+ break; /* End \P and \p */++ default: /* All others are not allowed in a class */+ errorcode = ERR7;+ ptr--;+ goto FAILED;+ }++ /* Perl gives a warning unless a following hyphen is the last character+ in the class. PCRE throws an error. */++ if (ptr < ptrend - 1 && *ptr == CHAR_MINUS &&+ ptr[1] != CHAR_RIGHT_SQUARE_BRACKET)+ {+ errorcode = ERR50;+ goto FAILED;+ }+ }++ /* Proceed to next thing in the class. */++ CLASS_CONTINUE:+ if (ptr >= ptrend)+ {+ errorcode = ERR6; /* Missing terminating ']' */+ goto FAILED;+ }+ GETCHARINCTEST(c, ptr);+ if (c == CHAR_RIGHT_SQUARE_BRACKET && !inescq) break;+ } /* End of class-processing loop */++ /* -] at the end of a class is a literal '-' */++ if (class_range_state == RANGE_STARTED)+ {+ parsed_pattern[-1] = CHAR_MINUS;+ class_range_state = RANGE_NO;+ }++ *parsed_pattern++ = META_CLASS_END;+ break; /* End of character class */+++ /* ---- Opening parenthesis ---- */++ case CHAR_LEFT_PARENTHESIS:+ if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;++ /* If ( is not followed by ? it is either a capture or a special verb or an+ alpha assertion or a positive non-atomic lookahead. */++ if (*ptr != CHAR_QUESTION_MARK)+ {+ const char *vn;++ /* Handle capturing brackets (or non-capturing if auto-capture is turned+ off). */++ if (*ptr != CHAR_ASTERISK)+ {+ nest_depth++;+ if ((options & PCRE2_NO_AUTO_CAPTURE) == 0)+ {+ if (cb->bracount >= MAX_GROUP_NUMBER)+ {+ errorcode = ERR97;+ goto FAILED;+ }+ cb->bracount++;+ *parsed_pattern++ = META_CAPTURE | cb->bracount;+ }+ else *parsed_pattern++ = META_NOCAPTURE;+ }++ /* Do nothing for (* followed by end of pattern or ) so it gives a "bad+ quantifier" error rather than "(*MARK) must have an argument". */++ else if (ptrend - ptr <= 1 || (c = ptr[1]) == CHAR_RIGHT_PARENTHESIS)+ break;++ /* Handle "alpha assertions" such as (*pla:...). Most of these are+ synonyms for the historical symbolic assertions, but the script run and+ non-atomic lookaround ones are new. They are distinguished by starting+ with a lower case letter. Checking both ends of the alphabet makes this+ work in all character codes. */++ else if (CHMAX_255(c) && (cb->ctypes[c] & ctype_lcletter) != 0)+ {+ uint32_t meta;++ vn = alasnames;+ if (!read_name(&ptr, ptrend, utf, 0, &offset, &name, &namelen,+ &errorcode, cb)) goto FAILED;+ if (ptr >= ptrend || *ptr != CHAR_COLON)+ {+ errorcode = ERR95; /* Malformed */+ goto FAILED;+ }++ /* Scan the table of alpha assertion names */++ for (i = 0; i < alascount; i++)+ {+ if (namelen == alasmeta[i].len &&+ PRIV(strncmp_c8)(name, vn, namelen) == 0)+ break;+ vn += alasmeta[i].len + 1;+ }++ if (i >= alascount)+ {+ errorcode = ERR95; /* Alpha assertion not recognized */+ goto FAILED;+ }++ /* Check for expecting an assertion condition. If so, only atomic+ lookaround assertions are valid. */++ meta = alasmeta[i].meta;+ if (prev_expect_cond_assert > 0 &&+ (meta < META_LOOKAHEAD || meta > META_LOOKBEHINDNOT))+ {+ errorcode = (meta == META_LOOKAHEAD_NA || meta == META_LOOKBEHIND_NA)?+ ERR98 : ERR28; /* (Atomic) assertion expected */+ goto FAILED;+ }++ /* The lookaround alphabetic synonyms can mostly be handled by jumping+ to the code that handles the traditional symbolic forms. */++ switch(meta)+ {+ default:+ errorcode = ERR89; /* Unknown code; should never occur because */+ goto FAILED; /* the meta values come from a table above. */++ case META_ATOMIC:+ goto ATOMIC_GROUP;++ case META_LOOKAHEAD:+ goto POSITIVE_LOOK_AHEAD;++ case META_LOOKAHEAD_NA:+ goto POSITIVE_NONATOMIC_LOOK_AHEAD;++ case META_LOOKAHEADNOT:+ goto NEGATIVE_LOOK_AHEAD;++ case META_LOOKBEHIND:+ case META_LOOKBEHINDNOT:+ case META_LOOKBEHIND_NA:+ *parsed_pattern++ = meta;+ ptr--;+ goto POST_LOOKBEHIND;++ /* The script run facilities are handled here. Unicode support is+ required (give an error if not, as this is a security issue). Always+ record a META_SCRIPT_RUN item. Then, for the atomic version, insert+ META_ATOMIC and remember that we need two META_KETs at the end. */++ case META_SCRIPT_RUN:+ case META_ATOMIC_SCRIPT_RUN:+#ifdef SUPPORT_UNICODE+ *parsed_pattern++ = META_SCRIPT_RUN;+ nest_depth++;+ ptr++;+ if (meta == META_ATOMIC_SCRIPT_RUN)+ {+ *parsed_pattern++ = META_ATOMIC;+ if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);+ else if (++top_nest >= end_nests)+ {+ errorcode = ERR84;+ goto FAILED;+ }+ top_nest->nest_depth = nest_depth;+ top_nest->flags = NSF_ATOMICSR;+ top_nest->options = options & PARSE_TRACKED_OPTIONS;+ }+ break;+#else /* SUPPORT_UNICODE */+ errorcode = ERR96;+ goto FAILED;+#endif+ }+ }+++ /* ---- Handle (*VERB) and (*VERB:NAME) ---- */++ else+ {+ vn = verbnames;+ if (!read_name(&ptr, ptrend, utf, 0, &offset, &name, &namelen,+ &errorcode, cb)) goto FAILED;+ if (ptr >= ptrend || (*ptr != CHAR_COLON &&+ *ptr != CHAR_RIGHT_PARENTHESIS))+ {+ errorcode = ERR60; /* Malformed */+ goto FAILED;+ }++ /* Scan the table of verb names */++ for (i = 0; i < verbcount; i++)+ {+ if (namelen == verbs[i].len &&+ PRIV(strncmp_c8)(name, vn, namelen) == 0)+ break;+ vn += verbs[i].len + 1;+ }++ if (i >= verbcount)+ {+ errorcode = ERR60; /* Verb not recognized */+ goto FAILED;+ }++ /* An empty argument is treated as no argument. */++ if (*ptr == CHAR_COLON && ptr + 1 < ptrend &&+ ptr[1] == CHAR_RIGHT_PARENTHESIS)+ ptr++; /* Advance to the closing parens */++ /* Check for mandatory non-empty argument; this is (*MARK) */++ if (verbs[i].has_arg > 0 && *ptr != CHAR_COLON)+ {+ errorcode = ERR66;+ goto FAILED;+ }++ /* Remember where this verb, possibly with a preceding (*MARK), starts,+ for handling quantified (*ACCEPT). */++ verbstartptr = parsed_pattern;+ okquantifier = (verbs[i].meta == META_ACCEPT);++ /* It appears that Perl allows any characters whatsoever, other than a+ closing parenthesis, to appear in arguments ("names"), so we no longer+ insist on letters, digits, and underscores. Perl does not, however, do+ any interpretation within arguments, and has no means of including a+ closing parenthesis. PCRE supports escape processing but only when it+ is requested by an option. We set inverbname TRUE here, and let the+ main loop take care of this so that escape and \x processing is done by+ the main code above. */++ if (*ptr++ == CHAR_COLON) /* Skip past : or ) */+ {+ /* Some optional arguments can be treated as a preceding (*MARK) */++ if (verbs[i].has_arg < 0)+ {+ add_after_mark = verbs[i].meta;+ *parsed_pattern++ = META_MARK;+ }++ /* The remaining verbs with arguments (except *MARK) need a different+ opcode. */++ else+ {+ *parsed_pattern++ = verbs[i].meta ++ ((verbs[i].meta != META_MARK)? 0x00010000u:0);+ }++ /* Set up for reading the name in the main loop. */++ verblengthptr = parsed_pattern++;+ verbnamestart = ptr;+ inverbname = TRUE;+ }+ else /* No verb "name" argument */+ {+ *parsed_pattern++ = verbs[i].meta;+ }+ } /* End of (*VERB) handling */+ break; /* Done with this parenthesis */+ } /* End of groups that don't start with (? */+++ /* ---- Items starting (? ---- */++ /* The type of item is determined by what follows (?. Handle (?| and option+ changes under "default" because both need a new block on the nest stack.+ Comments starting with (?# are handled above. Note that there is some+ ambiguity about the sequence (?- because if a digit follows it's a relative+ recursion or subroutine call whereas otherwise it's an option unsetting. */++ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;++ switch(*ptr)+ {+ default:+ if (*ptr == CHAR_MINUS && ptrend - ptr > 1 && IS_DIGIT(ptr[1]))+ goto RECURSION_BYNUMBER; /* The + case is handled by CHAR_PLUS */++ /* We now have either (?| or a (possibly empty) option setting,+ optionally followed by a non-capturing group. */++ nest_depth++;+ if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);+ else if (++top_nest >= end_nests)+ {+ errorcode = ERR84;+ goto FAILED;+ }+ top_nest->nest_depth = nest_depth;+ top_nest->flags = 0;+ top_nest->options = options & PARSE_TRACKED_OPTIONS;++ /* Start of non-capturing group that resets the capture count for each+ branch. */++ if (*ptr == CHAR_VERTICAL_LINE)+ {+ top_nest->reset_group = (uint16_t)cb->bracount;+ top_nest->max_group = (uint16_t)cb->bracount;+ top_nest->flags |= NSF_RESET;+ cb->external_flags |= PCRE2_DUPCAPUSED;+ *parsed_pattern++ = META_NOCAPTURE;+ ptr++;+ }++ /* Scan for options imnsxJU to be set or unset. */++ else+ {+ BOOL hyphenok = TRUE;+ uint32_t oldoptions = options;++ top_nest->reset_group = 0;+ top_nest->max_group = 0;+ set = unset = 0;+ optset = &set;++ /* ^ at the start unsets imnsx and disables the subsequent use of - */++ if (ptr < ptrend && *ptr == CHAR_CIRCUMFLEX_ACCENT)+ {+ options &= ~(PCRE2_CASELESS|PCRE2_MULTILINE|PCRE2_NO_AUTO_CAPTURE|+ PCRE2_DOTALL|PCRE2_EXTENDED|PCRE2_EXTENDED_MORE);+ hyphenok = FALSE;+ ptr++;+ }++ while (ptr < ptrend && *ptr != CHAR_RIGHT_PARENTHESIS &&+ *ptr != CHAR_COLON)+ {+ switch (*ptr++)+ {+ case CHAR_MINUS:+ if (!hyphenok)+ {+ errorcode = ERR94;+ ptr--; /* Correct the offset */+ goto FAILED;+ }+ optset = &unset;+ hyphenok = FALSE;+ break;++ case CHAR_J: /* Record that it changed in the external options */+ *optset |= PCRE2_DUPNAMES;+ cb->external_flags |= PCRE2_JCHANGED;+ break;++ case CHAR_i: *optset |= PCRE2_CASELESS; break;+ case CHAR_m: *optset |= PCRE2_MULTILINE; break;+ case CHAR_n: *optset |= PCRE2_NO_AUTO_CAPTURE; break;+ case CHAR_s: *optset |= PCRE2_DOTALL; break;+ case CHAR_U: *optset |= PCRE2_UNGREEDY; break;++ /* If x appears twice it sets the extended extended option. */++ case CHAR_x:+ *optset |= PCRE2_EXTENDED;+ if (ptr < ptrend && *ptr == CHAR_x)+ {+ *optset |= PCRE2_EXTENDED_MORE;+ ptr++;+ }+ break;++ default:+ errorcode = ERR11;+ ptr--; /* Correct the offset */+ goto FAILED;+ }+ }++ /* If we are setting extended without extended-more, ensure that any+ existing extended-more gets unset. Also, unsetting extended must also+ unset extended-more. */++ if ((set & (PCRE2_EXTENDED|PCRE2_EXTENDED_MORE)) == PCRE2_EXTENDED ||+ (unset & PCRE2_EXTENDED) != 0)+ unset |= PCRE2_EXTENDED_MORE;++ options = (options | set) & (~unset);++ /* If the options ended with ')' this is not the start of a nested+ group with option changes, so the options change at this level.+ In this case, if the previous level set up a nest block, discard the+ one we have just created. Otherwise adjust it for the previous level.+ If the options ended with ':' we are starting a non-capturing group,+ possibly with an options setting. */++ if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;+ if (*ptr++ == CHAR_RIGHT_PARENTHESIS)+ {+ nest_depth--; /* This is not a nested group after all. */+ if (top_nest > (nest_save *)(cb->start_workspace) &&+ (top_nest-1)->nest_depth == nest_depth) top_nest--;+ else top_nest->nest_depth = nest_depth;+ }+ else *parsed_pattern++ = META_NOCAPTURE;++ /* If nothing changed, no need to record. */++ if (options != oldoptions)+ {+ *parsed_pattern++ = META_OPTIONS;+ *parsed_pattern++ = options;+ }+ } /* End options processing */+ break; /* End default case after (? */+++ /* ---- Python syntax support ---- */++ case CHAR_P:+ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;++ /* (?P<name> is the same as (?<name>, which defines a named group. */++ if (*ptr == CHAR_LESS_THAN_SIGN)+ {+ terminator = CHAR_GREATER_THAN_SIGN;+ goto DEFINE_NAME;+ }++ /* (?P>name) is the same as (?&name), which is a recursion or subroutine+ call. */++ if (*ptr == CHAR_GREATER_THAN_SIGN) goto RECURSE_BY_NAME;++ /* (?P=name) is the same as \k<name>, a back reference by name. Anything+ else after (?P is an error. */++ if (*ptr != CHAR_EQUALS_SIGN)+ {+ errorcode = ERR41;+ goto FAILED;+ }+ if (!read_name(&ptr, ptrend, utf, CHAR_RIGHT_PARENTHESIS, &offset, &name,+ &namelen, &errorcode, cb)) goto FAILED;+ *parsed_pattern++ = META_BACKREF_BYNAME;+ *parsed_pattern++ = namelen;+ PUTOFFSET(offset, parsed_pattern);+ okquantifier = TRUE;+ break; /* End of (?P processing */+++ /* ---- Recursion/subroutine calls by number ---- */++ case CHAR_R:+ i = 0; /* (?R) == (?R0) */+ ptr++;+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR58;+ goto FAILED;+ }+ goto SET_RECURSION;++ /* An item starting (?- followed by a digit comes here via the "default"+ case because (?- followed by a non-digit is an options setting. */++ case CHAR_PLUS:+ if (ptrend - ptr < 2 || !IS_DIGIT(ptr[1]))+ {+ errorcode = ERR29; /* Missing number */+ goto FAILED;+ }+ /* Fall through */++ case CHAR_0: case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4:+ case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:+ RECURSION_BYNUMBER:+ if (!read_number(&ptr, ptrend,+ (IS_DIGIT(*ptr))? -1:(int)(cb->bracount), /* + and - are relative */+ MAX_GROUP_NUMBER, ERR61,+ &i, &errorcode)) goto FAILED;+ if (i < 0) /* NB (?0) is permitted */+ {+ errorcode = ERR15; /* Unknown group */+ goto FAILED_BACK;+ }+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ goto UNCLOSED_PARENTHESIS;++ SET_RECURSION:+ *parsed_pattern++ = META_RECURSE | (uint32_t)i;+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern);+ ptr++;+ PUTOFFSET(offset, parsed_pattern);+ okquantifier = TRUE;+ break; /* End of recursive call by number handling */+++ /* ---- Recursion/subroutine calls by name ---- */++ case CHAR_AMPERSAND:+ RECURSE_BY_NAME:+ if (!read_name(&ptr, ptrend, utf, CHAR_RIGHT_PARENTHESIS, &offset, &name,+ &namelen, &errorcode, cb)) goto FAILED;+ *parsed_pattern++ = META_RECURSE_BYNAME;+ *parsed_pattern++ = namelen;+ PUTOFFSET(offset, parsed_pattern);+ okquantifier = TRUE;+ break;++ /* ---- Callout with numerical or string argument ---- */++ case CHAR_C:+ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;++ /* If the previous item was a condition starting (?(? an assertion,+ optionally preceded by a callout, is expected. This is checked later on,+ during actual compilation. However we need to identify this kind of+ assertion in this pass because it must not be qualified. The value of+ expect_cond_assert is set to 2 after (?(? is processed. We decrement it+ for a callout - still leaving a positive value that identifies the+ assertion. Multiple callouts or any other items will make it zero or+ less, which doesn't matter because they will cause an error later. */++ expect_cond_assert = prev_expect_cond_assert - 1;++ /* If previous_callout is not NULL, it means this follows a previous+ callout. If it was a manual callout, do nothing; this means its "length+ of next pattern item" field will remain zero. If it was an automatic+ callout, abolish it. */++ if (previous_callout != NULL && (options & PCRE2_AUTO_CALLOUT) != 0 &&+ previous_callout == parsed_pattern - 4 &&+ parsed_pattern[-1] == 255)+ parsed_pattern = previous_callout;++ /* Save for updating next pattern item length, and skip one item before+ completing. */++ previous_callout = parsed_pattern;+ after_manual_callout = 1;++ /* Handle a string argument; specific delimiter is required. */++ if (*ptr != CHAR_RIGHT_PARENTHESIS && !IS_DIGIT(*ptr))+ {+ PCRE2_SIZE calloutlength;+ PCRE2_SPTR startptr = ptr;++ delimiter = 0;+ for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)+ {+ if (*ptr == PRIV(callout_start_delims)[i])+ {+ delimiter = PRIV(callout_end_delims)[i];+ break;+ }+ }+ if (delimiter == 0)+ {+ errorcode = ERR82;+ goto FAILED;+ }++ *parsed_pattern = META_CALLOUT_STRING;+ parsed_pattern += 3; /* Skip pattern info */++ for (;;)+ {+ if (++ptr >= ptrend)+ {+ errorcode = ERR81;+ ptr = startptr; /* To give a more useful message */+ goto FAILED;+ }+ if (*ptr == delimiter && (++ptr >= ptrend || *ptr != delimiter))+ break;+ }++ calloutlength = (PCRE2_SIZE)(ptr - startptr);+ if (calloutlength > UINT32_MAX)+ {+ errorcode = ERR72;+ goto FAILED;+ }+ *parsed_pattern++ = (uint32_t)calloutlength;+ offset = (PCRE2_SIZE)(startptr - cb->start_pattern);+ PUTOFFSET(offset, parsed_pattern);+ }++ /* Handle a callout with an optional numerical argument, which must be+ less than or equal to 255. A missing argument gives 0. */++ else+ {+ int n = 0;+ *parsed_pattern = META_CALLOUT_NUMBER; /* Numerical callout */+ parsed_pattern += 3; /* Skip pattern info */+ while (ptr < ptrend && IS_DIGIT(*ptr))+ {+ n = n * 10 + *ptr++ - CHAR_0;+ if (n > 255)+ {+ errorcode = ERR38;+ goto FAILED;+ }+ }+ *parsed_pattern++ = n;+ }++ /* Both formats must have a closing parenthesis */++ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR39;+ goto FAILED;+ }+ ptr++;++ /* Remember the offset to the next item in the pattern, and set a default+ length. This should get updated after the next item is read. */++ previous_callout[1] = (uint32_t)(ptr - cb->start_pattern);+ previous_callout[2] = 0;+ break; /* End callout */+++ /* ---- Conditional group ---- */++ /* A condition can be an assertion, a number (referring to a numbered+ group's having been set), a name (referring to a named group), or 'R',+ referring to overall recursion. R<digits> and R&name are also permitted+ for recursion state tests. Numbers may be preceded by + or - to specify a+ relative group number.++ There are several syntaxes for testing a named group: (?(name)) is used+ by Python; Perl 5.10 onwards uses (?(<name>) or (?('name')).++ There are two unfortunate ambiguities. 'R' can be the recursive thing or+ the name 'R' (and similarly for 'R' followed by digits). 'DEFINE' can be+ the Perl DEFINE feature or the Python named test. We look for a name+ first; if not found, we try the other case.++ For compatibility with auto-callouts, we allow a callout to be specified+ before a condition that is an assertion. */++ case CHAR_LEFT_PARENTHESIS:+ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;+ nest_depth++;++ /* If the next character is ? or * there must be an assertion next+ (optionally preceded by a callout). We do not check this here, but+ instead we set expect_cond_assert to 2. If this is still greater than+ zero (callouts decrement it) when the next assertion is read, it will be+ marked as a condition that must not be repeated. A value greater than+ zero also causes checking that an assertion (possibly with callout)+ follows. */++ if (*ptr == CHAR_QUESTION_MARK || *ptr == CHAR_ASTERISK)+ {+ *parsed_pattern++ = META_COND_ASSERT;+ ptr--; /* Pull pointer back to the opening parenthesis. */+ expect_cond_assert = 2;+ break; /* End of conditional */+ }++ /* Handle (?([+-]number)... */++ if (read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &i,+ &errorcode))+ {+ if (i <= 0)+ {+ errorcode = ERR15;+ goto FAILED;+ }+ *parsed_pattern++ = META_COND_NUMBER;+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2);+ PUTOFFSET(offset, parsed_pattern);+ *parsed_pattern++ = i;+ }+ else if (errorcode != 0) goto FAILED; /* Number too big */++ /* No number found. Handle the special case (?(VERSION[>]=n.m)... */++ else if (ptrend - ptr >= 10 &&+ PRIV(strncmp_c8)(ptr, STRING_VERSION, 7) == 0 &&+ ptr[7] != CHAR_RIGHT_PARENTHESIS)+ {+ uint32_t ge = 0;+ int major = 0;+ int minor = 0;++ ptr += 7;+ if (*ptr == CHAR_GREATER_THAN_SIGN)+ {+ ge = 1;+ ptr++;+ }++ /* NOTE: cannot write IS_DIGIT(*(++ptr)) here because IS_DIGIT+ references its argument twice. */++ if (*ptr != CHAR_EQUALS_SIGN || (ptr++, !IS_DIGIT(*ptr)))+ goto BAD_VERSION_CONDITION;++ if (!read_number(&ptr, ptrend, -1, 1000, ERR79, &major, &errorcode))+ goto FAILED;++ if (ptr >= ptrend) goto BAD_VERSION_CONDITION;+ if (*ptr == CHAR_DOT)+ {+ if (++ptr >= ptrend || !IS_DIGIT(*ptr)) goto BAD_VERSION_CONDITION;+ minor = (*ptr++ - CHAR_0) * 10;+ if (ptr >= ptrend) goto BAD_VERSION_CONDITION;+ if (IS_DIGIT(*ptr)) minor += *ptr++ - CHAR_0;+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ goto BAD_VERSION_CONDITION;+ }++ *parsed_pattern++ = META_COND_VERSION;+ *parsed_pattern++ = ge;+ *parsed_pattern++ = major;+ *parsed_pattern++ = minor;+ }++ /* All the remaining cases now require us to read a name. We cannot at+ this stage distinguish ambiguous cases such as (?(R12) which might be a+ recursion test by number or a name, because the named groups have not yet+ all been identified. Those cases are treated as names, but given a+ different META code. */++ else+ {+ BOOL was_r_ampersand = FALSE;++ if (*ptr == CHAR_R && ptrend - ptr > 1 && ptr[1] == CHAR_AMPERSAND)+ {+ terminator = CHAR_RIGHT_PARENTHESIS;+ was_r_ampersand = TRUE;+ ptr++;+ }+ else if (*ptr == CHAR_LESS_THAN_SIGN)+ terminator = CHAR_GREATER_THAN_SIGN;+ else if (*ptr == CHAR_APOSTROPHE)+ terminator = CHAR_APOSTROPHE;+ else+ {+ terminator = CHAR_RIGHT_PARENTHESIS;+ ptr--; /* Point to char before name */+ }+ if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,+ &errorcode, cb)) goto FAILED;++ /* Handle (?(R&name) */++ if (was_r_ampersand)+ {+ *parsed_pattern = META_COND_RNAME;+ ptr--; /* Back to closing parens */+ }++ /* Handle (?(name). If the name is "DEFINE" we identify it with a+ special code. Likewise if the name consists of R followed only by+ digits. Otherwise, handle it like a quoted name. */++ else if (terminator == CHAR_RIGHT_PARENTHESIS)+ {+ if (namelen == 6 && PRIV(strncmp_c8)(name, STRING_DEFINE, 6) == 0)+ *parsed_pattern = META_COND_DEFINE;+ else+ {+ for (i = 1; i < (int)namelen; i++)+ if (!IS_DIGIT(name[i])) break;+ *parsed_pattern = (*name == CHAR_R && i >= (int)namelen)?+ META_COND_RNUMBER : META_COND_NAME;+ }+ ptr--; /* Back to closing parens */+ }++ /* Handle (?('name') or (?(<name>) */++ else *parsed_pattern = META_COND_NAME;++ /* All these cases except DEFINE end with the name length and offset;+ DEFINE just has an offset (for the "too many branches" error). */++ if (*parsed_pattern++ != META_COND_DEFINE) *parsed_pattern++ = namelen;+ PUTOFFSET(offset, parsed_pattern);+ } /* End cases that read a name */++ /* Check the closing parenthesis of the condition */++ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR24;+ goto FAILED;+ }+ ptr++;+ break; /* End of condition processing */+++ /* ---- Atomic group ---- */++ case CHAR_GREATER_THAN_SIGN:+ ATOMIC_GROUP: /* Come from (*atomic: */+ *parsed_pattern++ = META_ATOMIC;+ nest_depth++;+ ptr++;+ break;+++ /* ---- Lookahead assertions ---- */++ case CHAR_EQUALS_SIGN:+ POSITIVE_LOOK_AHEAD: /* Come from (*pla: */+ *parsed_pattern++ = META_LOOKAHEAD;+ ptr++;+ goto POST_ASSERTION;++ case CHAR_ASTERISK:+ POSITIVE_NONATOMIC_LOOK_AHEAD: /* Come from (?* */+ *parsed_pattern++ = META_LOOKAHEAD_NA;+ ptr++;+ goto POST_ASSERTION;++ case CHAR_EXCLAMATION_MARK:+ NEGATIVE_LOOK_AHEAD: /* Come from (*nla: */+ *parsed_pattern++ = META_LOOKAHEADNOT;+ ptr++;+ goto POST_ASSERTION;+++ /* ---- Lookbehind assertions ---- */++ /* (?< followed by = or ! or * is a lookbehind assertion. Otherwise (?<+ is the start of the name of a capturing group. */++ case CHAR_LESS_THAN_SIGN:+ if (ptrend - ptr <= 1 ||+ (ptr[1] != CHAR_EQUALS_SIGN &&+ ptr[1] != CHAR_EXCLAMATION_MARK &&+ ptr[1] != CHAR_ASTERISK))+ {+ terminator = CHAR_GREATER_THAN_SIGN;+ goto DEFINE_NAME;+ }+ *parsed_pattern++ = (ptr[1] == CHAR_EQUALS_SIGN)?+ META_LOOKBEHIND : (ptr[1] == CHAR_EXCLAMATION_MARK)?+ META_LOOKBEHINDNOT : META_LOOKBEHIND_NA;++ POST_LOOKBEHIND: /* Come from (*plb: (*naplb: and (*nlb: */+ *has_lookbehind = TRUE;+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2);+ PUTOFFSET(offset, parsed_pattern);+ ptr += 2;+ /* Fall through */++ /* If the previous item was a condition starting (?(? an assertion,+ optionally preceded by a callout, is expected. This is checked later on,+ during actual compilation. However we need to identify this kind of+ assertion in this pass because it must not be qualified. The value of+ expect_cond_assert is set to 2 after (?(? is processed. We decrement it+ for a callout - still leaving a positive value that identifies the+ assertion. Multiple callouts or any other items will make it zero or+ less, which doesn't matter because they will cause an error later. */++ POST_ASSERTION:+ nest_depth++;+ if (prev_expect_cond_assert > 0)+ {+ if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);+ else if (++top_nest >= end_nests)+ {+ errorcode = ERR84;+ goto FAILED;+ }+ top_nest->nest_depth = nest_depth;+ top_nest->flags = NSF_CONDASSERT;+ top_nest->options = options & PARSE_TRACKED_OPTIONS;+ }+ break;+++ /* ---- Define a named group ---- */++ /* A named group may be defined as (?'name') or (?<name>). In the latter+ case we jump to DEFINE_NAME from the disambiguation of (?< above with the+ terminator set to '>'. */++ case CHAR_APOSTROPHE:+ terminator = CHAR_APOSTROPHE; /* Terminator */++ DEFINE_NAME:+ if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,+ &errorcode, cb)) goto FAILED;++ /* We have a name for this capturing group. It is also assigned a number,+ which is its primary means of identification. */++ if (cb->bracount >= MAX_GROUP_NUMBER)+ {+ errorcode = ERR97;+ goto FAILED;+ }+ cb->bracount++;+ *parsed_pattern++ = META_CAPTURE | cb->bracount;+ nest_depth++;++ /* Check not too many names */++ if (cb->names_found >= MAX_NAME_COUNT)+ {+ errorcode = ERR49;+ goto FAILED;+ }++ /* Adjust the entry size to accommodate the longest name found. */++ if (namelen + IMM2_SIZE + 1 > cb->name_entry_size)+ cb->name_entry_size = (uint16_t)(namelen + IMM2_SIZE + 1);++ /* Scan the list to check for duplicates. For duplicate names, if the+ number is the same, break the loop, which causes the name to be+ discarded; otherwise, if DUPNAMES is not set, give an error.+ If it is set, allow the name with a different number, but continue+ scanning in case this is a duplicate with the same number. For+ non-duplicate names, give an error if the number is duplicated. */++ isdupname = FALSE;+ ng = cb->named_groups;+ for (i = 0; i < cb->names_found; i++, ng++)+ {+ if (namelen == ng->length &&+ PRIV(strncmp)(name, ng->name, (PCRE2_SIZE)namelen) == 0)+ {+ if (ng->number == cb->bracount) break;+ if ((options & PCRE2_DUPNAMES) == 0)+ {+ errorcode = ERR43;+ goto FAILED;+ }+ isdupname = ng->isdup = TRUE; /* Mark as a duplicate */+ cb->dupnames = TRUE; /* Duplicate names exist */+ }+ else if (ng->number == cb->bracount)+ {+ errorcode = ERR65;+ goto FAILED;+ }+ }++ if (i < cb->names_found) break; /* Ignore duplicate with same number */++ /* Increase the list size if necessary */++ if (cb->names_found >= cb->named_group_list_size)+ {+ uint32_t newsize = cb->named_group_list_size * 2;+ named_group *newspace =+ cb->cx->memctl.malloc(newsize * sizeof(named_group),+ cb->cx->memctl.memory_data);+ if (newspace == NULL)+ {+ errorcode = ERR21;+ goto FAILED;+ }++ memcpy(newspace, cb->named_groups,+ cb->named_group_list_size * sizeof(named_group));+ if (cb->named_group_list_size > NAMED_GROUP_LIST_SIZE)+ cb->cx->memctl.free((void *)cb->named_groups,+ cb->cx->memctl.memory_data);+ cb->named_groups = newspace;+ cb->named_group_list_size = newsize;+ }++ /* Add this name to the list */++ cb->named_groups[cb->names_found].name = name;+ cb->named_groups[cb->names_found].length = (uint16_t)namelen;+ cb->named_groups[cb->names_found].number = cb->bracount;+ cb->named_groups[cb->names_found].isdup = (uint16_t)isdupname;+ cb->names_found++;+ break;+ } /* End of (? switch */+ break; /* End of ( handling */+++ /* ---- Branch terminators ---- */++ /* Alternation: reset the capture count if we are in a (?| group. */++ case CHAR_VERTICAL_LINE:+ if (top_nest != NULL && top_nest->nest_depth == nest_depth &&+ (top_nest->flags & NSF_RESET) != 0)+ {+ if (cb->bracount > top_nest->max_group)+ top_nest->max_group = (uint16_t)cb->bracount;+ cb->bracount = top_nest->reset_group;+ }+ *parsed_pattern++ = META_ALT;+ break;++ /* End of group; reset the capture count to the maximum if we are in a (?|+ group and/or reset the options that are tracked during parsing. Disallow+ quantifier for a condition that is an assertion. */++ case CHAR_RIGHT_PARENTHESIS:+ okquantifier = TRUE;+ if (top_nest != NULL && top_nest->nest_depth == nest_depth)+ {+ options = (options & ~PARSE_TRACKED_OPTIONS) | top_nest->options;+ if ((top_nest->flags & NSF_RESET) != 0 &&+ top_nest->max_group > cb->bracount)+ cb->bracount = top_nest->max_group;+ if ((top_nest->flags & NSF_CONDASSERT) != 0)+ okquantifier = FALSE;++ if ((top_nest->flags & NSF_ATOMICSR) != 0)+ {+ *parsed_pattern++ = META_KET;+ }++ if (top_nest == (nest_save *)(cb->start_workspace)) top_nest = NULL;+ else top_nest--;+ }+ if (nest_depth == 0) /* Unmatched closing parenthesis */+ {+ errorcode = ERR22;+ goto FAILED_BACK;+ }+ nest_depth--;+ *parsed_pattern++ = META_KET;+ break;+ } /* End of switch on pattern character */+ } /* End of main character scan loop */++/* End of pattern reached. Check for missing ) at the end of a verb name. */++if (inverbname && ptr >= ptrend)+ {+ errorcode = ERR60;+ goto FAILED;+ }++/* Manage callout for the final item */++PARSED_END:+parsed_pattern = manage_callouts(ptr, &previous_callout, auto_callout,+ parsed_pattern, cb);++/* Insert trailing items for word and line matching (features provided for the+benefit of pcre2grep). */++if ((extra_options & PCRE2_EXTRA_MATCH_LINE) != 0)+ {+ *parsed_pattern++ = META_KET;+ *parsed_pattern++ = META_DOLLAR;+ }+else if ((extra_options & PCRE2_EXTRA_MATCH_WORD) != 0)+ {+ *parsed_pattern++ = META_KET;+ *parsed_pattern++ = META_ESCAPE + ESC_b;+ }++/* Terminate the parsed pattern, then return success if all groups are closed.+Otherwise we have unclosed parentheses. */++if (parsed_pattern >= parsed_pattern_end)+ {+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */+ goto FAILED;+ }++*parsed_pattern = META_END;+if (nest_depth == 0) return 0;++UNCLOSED_PARENTHESIS:+errorcode = ERR14;++/* Come here for all failures. */++FAILED:+cb->erroroffset = (PCRE2_SIZE)(ptr - cb->start_pattern);+return errorcode;++/* Some errors need to indicate the previous character. */++FAILED_BACK:+ptr--;+goto FAILED;++/* This failure happens several times. */++BAD_VERSION_CONDITION:+errorcode = ERR79;+goto FAILED;+}++++/*************************************************+* Find first significant opcode *+*************************************************/++/* This is called by several functions that scan a compiled expression looking+for a fixed first character, or an anchoring opcode etc. It skips over things+that do not influence this. For some calls, it makes sense to skip negative+forward and all backward assertions, and also the \b assertion; for others it+does not.++Arguments:+ code pointer to the start of the group+ skipassert TRUE if certain assertions are to be skipped++Returns: pointer to the first significant opcode+*/++static const PCRE2_UCHAR*+first_significant_code(PCRE2_SPTR code, BOOL skipassert)+{+for (;;)+ {+ switch ((int)*code)+ {+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERTBACK_NA:+ if (!skipassert) return code;+ do code += GET(code, 1); while (*code == OP_ALT);+ code += PRIV(OP_lengths)[*code];+ break;++ case OP_WORD_BOUNDARY:+ case OP_NOT_WORD_BOUNDARY:+ if (!skipassert) return code;+ /* Fall through */++ case OP_CALLOUT:+ case OP_CREF:+ case OP_DNCREF:+ case OP_RREF:+ case OP_DNRREF:+ case OP_FALSE:+ case OP_TRUE:+ code += PRIV(OP_lengths)[*code];+ break;++ case OP_CALLOUT_STR:+ code += GET(code, 1 + 2*LINK_SIZE);+ break;++ case OP_SKIPZERO:+ code += 2 + GET(code, 2) + LINK_SIZE;+ break;++ case OP_COND:+ case OP_SCOND:+ if (code[1+LINK_SIZE] != OP_FALSE || /* Not DEFINE */+ code[GET(code, 1)] != OP_KET) /* More than one branch */+ return code;+ code += GET(code, 1) + 1 + LINK_SIZE;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ code += code[1] + PRIV(OP_lengths)[*code];+ break;++ default:+ return code;+ }+ }+/* Control never reaches here */+}++++#ifdef SUPPORT_UNICODE+/*************************************************+* Get othercase range *+*************************************************/++/* This function is passed the start and end of a class range in UCP mode. It+searches up the characters, looking for ranges of characters in the "other"+case. Each call returns the next one, updating the start address. A character+with multiple other cases is returned on its own with a special return value.++Arguments:+ cptr points to starting character value; updated+ d end value+ ocptr where to put start of othercase range+ odptr where to put end of othercase range++Yield: -1 when no more+ 0 when a range is returned+ >0 the CASESET offset for char with multiple other cases+ in this case, ocptr contains the original+*/++static int+get_othercase_range(uint32_t *cptr, uint32_t d, uint32_t *ocptr,+ uint32_t *odptr)+{+uint32_t c, othercase, next;+unsigned int co;++/* Find the first character that has an other case. If it has multiple other+cases, return its case offset value. */++for (c = *cptr; c <= d; c++)+ {+ if ((co = UCD_CASESET(c)) != 0)+ {+ *ocptr = c++; /* Character that has the set */+ *cptr = c; /* Rest of input range */+ return (int)co;+ }+ if ((othercase = UCD_OTHERCASE(c)) != c) break;+ }++if (c > d) return -1; /* Reached end of range */++/* Found a character that has a single other case. Search for the end of the+range, which is either the end of the input range, or a character that has zero+or more than one other cases. */++*ocptr = othercase;+next = othercase + 1;++for (++c; c <= d; c++)+ {+ if ((co = UCD_CASESET(c)) != 0 || UCD_OTHERCASE(c) != next) break;+ next++;+ }++*odptr = next - 1; /* End of othercase range */+*cptr = c; /* Rest of input range */+return 0;+}+#endif /* SUPPORT_UNICODE */++++/*************************************************+* Add a character or range to a class (internal) *+*************************************************/++/* This function packages up the logic of adding a character or range of+characters to a class. The character values in the arguments will be within the+valid values for the current mode (8-bit, 16-bit, UTF, etc). This function is+called only from within the "add to class" group of functions, some of which+are recursive and mutually recursive. The external entry point is+add_to_class().++Arguments:+ classbits the bit map for characters < 256+ uchardptr points to the pointer for extra data+ options the options word+ cb compile data+ start start of range character+ end end of range character++Returns: the number of < 256 characters added+ the pointer to extra data is updated+*/++static unsigned int+add_to_class_internal(uint8_t *classbits, PCRE2_UCHAR **uchardptr,+ uint32_t options, compile_block *cb, uint32_t start, uint32_t end)+{+uint32_t c;+uint32_t classbits_end = (end <= 0xff ? end : 0xff);+unsigned int n8 = 0;++/* If caseless matching is required, scan the range and process alternate+cases. In Unicode, there are 8-bit characters that have alternate cases that+are greater than 255 and vice-versa. Sometimes we can just extend the original+range. */++if ((options & PCRE2_CASELESS) != 0)+ {+#ifdef SUPPORT_UNICODE+ if ((options & (PCRE2_UTF|PCRE2_UCP)) != 0)+ {+ int rc;+ uint32_t oc, od;++ options &= ~PCRE2_CASELESS; /* Remove for recursive calls */+ c = start;++ while ((rc = get_othercase_range(&c, end, &oc, &od)) >= 0)+ {+ /* Handle a single character that has more than one other case. */++ if (rc > 0) n8 += add_list_to_class_internal(classbits, uchardptr, options, cb,+ PRIV(ucd_caseless_sets) + rc, oc);++ /* Do nothing if the other case range is within the original range. */++ else if (oc >= cb->class_range_start && od <= cb->class_range_end) continue;++ /* Extend the original range if there is overlap, noting that if oc < c, we+ can't have od > end because a subrange is always shorter than the basic+ range. Otherwise, use a recursive call to add the additional range. */++ else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */+ else if (od > end && oc <= end + 1)+ {+ end = od; /* Extend upwards */+ if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff);+ }+ else n8 += add_to_class_internal(classbits, uchardptr, options, cb, oc, od);+ }+ }+ else+#endif /* SUPPORT_UNICODE */++ /* Not UTF mode */++ for (c = start; c <= classbits_end; c++)+ {+ SETBIT(classbits, cb->fcc[c]);+ n8++;+ }+ }++/* Now handle the originally supplied range. Adjust the final value according+to the bit length - this means that the same lists of (e.g.) horizontal spaces+can be used in all cases. */++if ((options & PCRE2_UTF) == 0 && end > MAX_NON_UTF_CHAR)+ end = MAX_NON_UTF_CHAR;++if (start > cb->class_range_start && end < cb->class_range_end) return n8;++/* Use the bitmap for characters < 256. Otherwise use extra data.*/++for (c = start; c <= classbits_end; c++)+ {+ /* Regardless of start, c will always be <= 255. */+ SETBIT(classbits, c);+ n8++;+ }++#ifdef SUPPORT_WIDE_CHARS+if (start <= 0xff) start = 0xff + 1;++if (end >= start)+ {+ PCRE2_UCHAR *uchardata = *uchardptr;++#ifdef SUPPORT_UNICODE+ if ((options & PCRE2_UTF) != 0)+ {+ if (start < end)+ {+ *uchardata++ = XCL_RANGE;+ uchardata += PRIV(ord2utf)(start, uchardata);+ uchardata += PRIV(ord2utf)(end, uchardata);+ }+ else if (start == end)+ {+ *uchardata++ = XCL_SINGLE;+ uchardata += PRIV(ord2utf)(start, uchardata);+ }+ }+ else+#endif /* SUPPORT_UNICODE */++ /* Without UTF support, character values are constrained by the bit length,+ and can only be > 256 for 16-bit and 32-bit libraries. */++#if PCRE2_CODE_UNIT_WIDTH == 8+ {}+#else+ if (start < end)+ {+ *uchardata++ = XCL_RANGE;+ *uchardata++ = start;+ *uchardata++ = end;+ }+ else if (start == end)+ {+ *uchardata++ = XCL_SINGLE;+ *uchardata++ = start;+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ *uchardptr = uchardata; /* Updata extra data pointer */+ }+#else /* SUPPORT_WIDE_CHARS */+ (void)uchardptr; /* Avoid compiler warning */+#endif /* SUPPORT_WIDE_CHARS */++return n8; /* Number of 8-bit characters */+}++++#ifdef SUPPORT_UNICODE+/*************************************************+* Add a list of characters to a class (internal) *+*************************************************/++/* This function is used for adding a list of case-equivalent characters to a+class when in UTF mode. This function is called only from within+add_to_class_internal(), with which it is mutually recursive.++Arguments:+ classbits the bit map for characters < 256+ uchardptr points to the pointer for extra data+ options the options word+ cb contains pointers to tables etc.+ p points to row of 32-bit values, terminated by NOTACHAR+ except character to omit; this is used when adding lists of+ case-equivalent characters to avoid including the one we+ already know about++Returns: the number of < 256 characters added+ the pointer to extra data is updated+*/++static unsigned int+add_list_to_class_internal(uint8_t *classbits, PCRE2_UCHAR **uchardptr,+ uint32_t options, compile_block *cb, const uint32_t *p, unsigned int except)+{+unsigned int n8 = 0;+while (p[0] < NOTACHAR)+ {+ unsigned int n = 0;+ if (p[0] != except)+ {+ while(p[n+1] == p[0] + n + 1) n++;+ n8 += add_to_class_internal(classbits, uchardptr, options, cb, p[0], p[n]);+ }+ p += n + 1;+ }+return n8;+}+#endif++++/*************************************************+* External entry point for add range to class *+*************************************************/++/* This function sets the overall range so that the internal functions can try+to avoid duplication when handling case-independence.++Arguments:+ classbits the bit map for characters < 256+ uchardptr points to the pointer for extra data+ options the options word+ cb compile data+ start start of range character+ end end of range character++Returns: the number of < 256 characters added+ the pointer to extra data is updated+*/++static unsigned int+add_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options,+ compile_block *cb, uint32_t start, uint32_t end)+{+cb->class_range_start = start;+cb->class_range_end = end;+return add_to_class_internal(classbits, uchardptr, options, cb, start, end);+}+++/*************************************************+* External entry point for add list to class *+*************************************************/++/* This function is used for adding a list of horizontal or vertical whitespace+characters to a class. The list must be in order so that ranges of characters+can be detected and handled appropriately. This function sets the overall range+so that the internal functions can try to avoid duplication when handling+case-independence.++Arguments:+ classbits the bit map for characters < 256+ uchardptr points to the pointer for extra data+ options the options word+ cb contains pointers to tables etc.+ p points to row of 32-bit values, terminated by NOTACHAR+ except character to omit; this is used when adding lists of+ case-equivalent characters to avoid including the one we+ already know about++Returns: the number of < 256 characters added+ the pointer to extra data is updated+*/++static unsigned int+add_list_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options,+ compile_block *cb, const uint32_t *p, unsigned int except)+{+unsigned int n8 = 0;+while (p[0] < NOTACHAR)+ {+ unsigned int n = 0;+ if (p[0] != except)+ {+ while(p[n+1] == p[0] + n + 1) n++;+ cb->class_range_start = p[0];+ cb->class_range_end = p[n];+ n8 += add_to_class_internal(classbits, uchardptr, options, cb, p[0], p[n]);+ }+ p += n + 1;+ }+return n8;+}++++/*************************************************+* Add characters not in a list to a class *+*************************************************/++/* This function is used for adding the complement of a list of horizontal or+vertical whitespace to a class. The list must be in order.++Arguments:+ classbits the bit map for characters < 256+ uchardptr points to the pointer for extra data+ options the options word+ cb contains pointers to tables etc.+ p points to row of 32-bit values, terminated by NOTACHAR++Returns: the number of < 256 characters added+ the pointer to extra data is updated+*/++static unsigned int+add_not_list_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr,+ uint32_t options, compile_block *cb, const uint32_t *p)+{+BOOL utf = (options & PCRE2_UTF) != 0;+unsigned int n8 = 0;+if (p[0] > 0)+ n8 += add_to_class(classbits, uchardptr, options, cb, 0, p[0] - 1);+while (p[0] < NOTACHAR)+ {+ while (p[1] == p[0] + 1) p++;+ n8 += add_to_class(classbits, uchardptr, options, cb, p[0] + 1,+ (p[1] == NOTACHAR) ? (utf ? 0x10ffffu : 0xffffffffu) : p[1] - 1);+ p++;+ }+return n8;+}++++/*************************************************+* Find details of duplicate group names *+*************************************************/++/* This is called from compile_branch() when it needs to know the index and+count of duplicates in the names table when processing named backreferences,+either directly, or as conditions.++Arguments:+ name points to the name+ length the length of the name+ indexptr where to put the index+ countptr where to put the count of duplicates+ errorcodeptr where to put an error code+ cb the compile block++Returns: TRUE if OK, FALSE if not, error code set+*/++static BOOL+find_dupname_details(PCRE2_SPTR name, uint32_t length, int *indexptr,+ int *countptr, int *errorcodeptr, compile_block *cb)+{+uint32_t i, groupnumber;+int count;+PCRE2_UCHAR *slot = cb->name_table;++/* Find the first entry in the table */++for (i = 0; i < cb->names_found; i++)+ {+ if (PRIV(strncmp)(name, slot+IMM2_SIZE, length) == 0 &&+ slot[IMM2_SIZE+length] == 0) break;+ slot += cb->name_entry_size;+ }++/* This should not occur, because this function is called only when we know we+have duplicate names. Give an internal error. */++if (i >= cb->names_found)+ {+ *errorcodeptr = ERR53;+ cb->erroroffset = name - cb->start_pattern;+ return FALSE;+ }++/* Record the index and then see how many duplicates there are, updating the+backref map and maximum back reference as we do. */++*indexptr = i;+count = 0;++for (;;)+ {+ count++;+ groupnumber = GET2(slot,0);+ cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;+ if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;+ if (++i >= cb->names_found) break;+ slot += cb->name_entry_size;+ if (PRIV(strncmp)(name, slot+IMM2_SIZE, length) != 0 ||+ (slot+IMM2_SIZE)[length] != 0) break;+ }++*countptr = count;+return TRUE;+}++++/*************************************************+* Compile one branch *+*************************************************/++/* Scan the parsed pattern, compiling it into the a vector of PCRE2_UCHAR. If+the options are changed during the branch, the pointer is used to change the+external options bits. This function is used during the pre-compile phase when+we are trying to find out the amount of memory needed, as well as during the+real compile phase. The value of lengthptr distinguishes the two phases.++Arguments:+ optionsptr pointer to the option bits+ codeptr points to the pointer to the current code point+ pptrptr points to the current parsed pattern pointer+ errorcodeptr points to error code variable+ firstcuptr place to put the first required code unit+ firstcuflagsptr place to put the first code unit flags, or a negative number+ reqcuptr place to put the last required code unit+ reqcuflagsptr place to put the last required code unit flags, or a negative number+ bcptr points to current branch chain+ cb contains pointers to tables etc.+ lengthptr NULL during the real compile phase+ points to length accumulator during pre-compile phase++Returns: 0 There's been an error, *errorcodeptr is non-zero+ +1 Success, this branch must match at least one character+ -1 Success, this branch may match an empty string+*/++static int+compile_branch(uint32_t *optionsptr, PCRE2_UCHAR **codeptr, uint32_t **pptrptr,+ int *errorcodeptr, uint32_t *firstcuptr, int32_t *firstcuflagsptr,+ uint32_t *reqcuptr, int32_t *reqcuflagsptr, branch_chain *bcptr,+ compile_block *cb, PCRE2_SIZE *lengthptr)+{+int bravalue = 0;+int okreturn = -1;+int group_return = 0;+uint32_t repeat_min = 0, repeat_max = 0; /* To please picky compilers */+uint32_t greedy_default, greedy_non_default;+uint32_t repeat_type, op_type;+uint32_t options = *optionsptr; /* May change dynamically */+uint32_t firstcu, reqcu;+uint32_t zeroreqcu, zerofirstcu;+uint32_t escape;+uint32_t *pptr = *pptrptr;+uint32_t meta, meta_arg;+int32_t firstcuflags, reqcuflags;+int32_t zeroreqcuflags, zerofirstcuflags;+int32_t req_caseopt, reqvary, tempreqvary;+PCRE2_SIZE offset = 0;+PCRE2_SIZE length_prevgroup = 0;+PCRE2_UCHAR *code = *codeptr;+PCRE2_UCHAR *last_code = code;+PCRE2_UCHAR *orig_code = code;+PCRE2_UCHAR *tempcode;+PCRE2_UCHAR *previous = NULL;+PCRE2_UCHAR op_previous;+BOOL groupsetfirstcu = FALSE;+BOOL had_accept = FALSE;+BOOL matched_char = FALSE;+BOOL previous_matched_char = FALSE;+BOOL reset_caseful = FALSE;+const uint8_t *cbits = cb->cbits;+uint8_t classbits[32];++/* We can fish out the UTF setting once and for all into a BOOL, but we must+not do this for other options (e.g. PCRE2_EXTENDED) because they may change+dynamically as we process the pattern. */++#ifdef SUPPORT_UNICODE+BOOL utf = (options & PCRE2_UTF) != 0;+BOOL ucp = (options & PCRE2_UCP) != 0;+#else /* No Unicode support */+BOOL utf = FALSE;+#endif++/* Helper variables for OP_XCLASS opcode (for characters > 255). We define+class_uchardata always so that it can be passed to add_to_class() always,+though it will not be used in non-UTF 8-bit cases. This avoids having to supply+alternative calls for the different cases. */++PCRE2_UCHAR *class_uchardata;+#ifdef SUPPORT_WIDE_CHARS+BOOL xclass;+PCRE2_UCHAR *class_uchardata_base;+#endif++/* Set up the default and non-default settings for greediness */++greedy_default = ((options & PCRE2_UNGREEDY) != 0);+greedy_non_default = greedy_default ^ 1;++/* Initialize no first unit, no required unit. REQ_UNSET means "no char+matching encountered yet". It gets changed to REQ_NONE if we hit something that+matches a non-fixed first unit; reqcu just remains unset if we never find one.++When we hit a repeat whose minimum is zero, we may have to adjust these values+to take the zero repeat into account. This is implemented by setting them to+zerofirstcu and zeroreqcu when such a repeat is encountered. The individual+item types that can be repeated set these backoff variables appropriately. */++firstcu = reqcu = zerofirstcu = zeroreqcu = 0;+firstcuflags = reqcuflags = zerofirstcuflags = zeroreqcuflags = REQ_UNSET;++/* The variable req_caseopt contains either the REQ_CASELESS value or zero,+according to the current setting of the caseless flag. The REQ_CASELESS value+leaves the lower 28 bit empty. It is added into the firstcu or reqcu variables+to record the case status of the value. This is used only for ASCII characters.+*/++req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS:0;++/* Switch on next META item until the end of the branch */++for (;; pptr++)+ {+#ifdef SUPPORT_WIDE_CHARS+ BOOL xclass_has_prop;+#endif+ BOOL negate_class;+ BOOL should_flip_negation;+ BOOL match_all_or_no_wide_chars;+ BOOL possessive_quantifier;+ BOOL note_group_empty;+ int class_has_8bitchar;+ int i;+ uint32_t mclength;+ uint32_t skipunits;+ uint32_t subreqcu, subfirstcu;+ uint32_t groupnumber;+ uint32_t verbarglen, verbculen;+ int32_t subreqcuflags, subfirstcuflags; /* Must be signed */+ open_capitem *oc;+ PCRE2_UCHAR mcbuffer[8];++ /* Get next META item in the pattern and its potential argument. */++ meta = META_CODE(*pptr);+ meta_arg = META_DATA(*pptr);++ /* If we are in the pre-compile phase, accumulate the length used for the+ previous cycle of this loop, unless the next item is a quantifier. */++ if (lengthptr != NULL)+ {+ if (code > cb->start_workspace + cb->workspace_size -+ WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */+ {+ *errorcodeptr = (code >= cb->start_workspace + cb->workspace_size)?+ ERR52 : ERR86;+ return 0;+ }++ /* There is at least one situation where code goes backwards: this is the+ case of a zero quantifier after a class (e.g. [ab]{0}). When the quantifier+ is processed, the whole class is eliminated. However, it is created first,+ so we have to allow memory for it. Therefore, don't ever reduce the length+ at this point. */++ if (code < last_code) code = last_code;++ /* If the next thing is not a quantifier, we add the length of the previous+ item into the total, and reset the code pointer to the start of the+ workspace. Otherwise leave the previous item available to be quantified. */++ if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)+ {+ if (OFLOW_MAX - *lengthptr < (PCRE2_SIZE)(code - orig_code))+ {+ *errorcodeptr = ERR20; /* Integer overflow */+ return 0;+ }+ *lengthptr += (PCRE2_SIZE)(code - orig_code);+ if (*lengthptr > MAX_PATTERN_SIZE)+ {+ *errorcodeptr = ERR20; /* Pattern is too large */+ return 0;+ }+ code = orig_code;+ }++ /* Remember where this code item starts so we can catch the "backwards"+ case above next time round. */++ last_code = code;+ }++ /* Process the next parsed pattern item. If it is not a quantifier, remember+ where it starts so that it can be quantified when a quantifier follows.+ Checking for the legality of quantifiers happens in parse_regex(), except for+ a quantifier after an assertion that is a condition. */++ if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)+ {+ previous = code;+ if (matched_char && !had_accept) okreturn = 1;+ }++ previous_matched_char = matched_char;+ matched_char = FALSE;+ note_group_empty = FALSE;+ skipunits = 0; /* Default value for most subgroups */++ switch(meta)+ {+ /* ===================================================================*/+ /* The branch terminates at pattern end or | or ) */++ case META_END:+ case META_ALT:+ case META_KET:+ *firstcuptr = firstcu;+ *firstcuflagsptr = firstcuflags;+ *reqcuptr = reqcu;+ *reqcuflagsptr = reqcuflags;+ *codeptr = code;+ *pptrptr = pptr;+ return okreturn;+++ /* ===================================================================*/+ /* Handle single-character metacharacters. In multiline mode, ^ disables+ the setting of any following char as a first character. */++ case META_CIRCUMFLEX:+ if ((options & PCRE2_MULTILINE) != 0)+ {+ if (firstcuflags == REQ_UNSET)+ zerofirstcuflags = firstcuflags = REQ_NONE;+ *code++ = OP_CIRCM;+ }+ else *code++ = OP_CIRC;+ break;++ case META_DOLLAR:+ *code++ = ((options & PCRE2_MULTILINE) != 0)? OP_DOLLM : OP_DOLL;+ break;++ /* There can never be a first char if '.' is first, whatever happens about+ repeats. The value of reqcu doesn't change either. */++ case META_DOT:+ matched_char = TRUE;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;+ *code++ = ((options & PCRE2_DOTALL) != 0)? OP_ALLANY: OP_ANY;+ break;+++ /* ===================================================================*/+ /* Empty character classes are allowed if PCRE2_ALLOW_EMPTY_CLASS is set.+ Otherwise, an initial ']' is taken as a data character. When empty classes+ are allowed, [] must always fail, so generate OP_FAIL, whereas [^] must+ match any character, so generate OP_ALLANY. */++ case META_CLASS_EMPTY:+ case META_CLASS_EMPTY_NOT:+ matched_char = TRUE;+ *code++ = (meta == META_CLASS_EMPTY_NOT)? OP_ALLANY : OP_FAIL;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ break;+++ /* ===================================================================*/+ /* Non-empty character class. If the included characters are all < 256, we+ build a 32-byte bitmap of the permitted characters, except in the special+ case where there is only one such character. For negated classes, we build+ the map as usual, then invert it at the end. However, we use a different+ opcode so that data characters > 255 can be handled correctly.++ If the class contains characters outside the 0-255 range, a different+ opcode is compiled. It may optionally have a bit map for characters < 256,+ but those above are are explicitly listed afterwards. A flag code unit+ tells whether the bitmap is present, and whether this is a negated class or+ not. */++ case META_CLASS_NOT:+ case META_CLASS:+ matched_char = TRUE;+ negate_class = meta == META_CLASS_NOT;++ /* We can optimize the case of a single character in a class by generating+ OP_CHAR or OP_CHARI if it's positive, or OP_NOT or OP_NOTI if it's+ negative. In the negative case there can be no first char if this item is+ first, whatever repeat count may follow. In the case of reqcu, save the+ previous value for reinstating. */++ /* NOTE: at present this optimization is not effective if the only+ character in a class in 32-bit, non-UCP mode has its top bit set. */++ if (pptr[1] < META_END && pptr[2] == META_CLASS_END)+ {+#ifdef SUPPORT_UNICODE+ uint32_t d;+#endif+ uint32_t c = pptr[1];++ pptr += 2; /* Move on to class end */+ if (meta == META_CLASS) /* A positive one-char class can be */+ { /* handled as a normal literal character. */+ meta = c; /* Set up the character */+ goto NORMAL_CHAR_SET;+ }++ /* Handle a negative one-character class */++ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;++ /* For caseless UTF or UCP mode, check whether this character has more+ than one other case. If so, generate a special OP_NOTPROP item instead of+ OP_NOTI. */++#ifdef SUPPORT_UNICODE+ if ((utf||ucp) && (options & PCRE2_CASELESS) != 0 &&+ (d = UCD_CASESET(c)) != 0)+ {+ *code++ = OP_NOTPROP;+ *code++ = PT_CLIST;+ *code++ = d;+ break; /* We are finished with this class */+ }+#endif+ /* Char has only one other case, or UCP not available */++ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_NOTI: OP_NOT;+ code += PUTCHAR(c, code);+ break; /* We are finished with this class */+ } /* End of 1-char optimization */++ /* Handle character classes that contain more than just one literal+ character. If there are exactly two characters in a positive class, see if+ they are case partners. This can be optimized to generate a caseless single+ character match (which also sets first/required code units if relevant). */++ if (meta == META_CLASS && pptr[1] < META_END && pptr[2] < META_END &&+ pptr[3] == META_CLASS_END)+ {+ uint32_t c = pptr[1];++#ifdef SUPPORT_UNICODE+ if (UCD_CASESET(c) == 0)+#endif+ {+ uint32_t d;++#ifdef SUPPORT_UNICODE+ if ((utf || ucp) && c > 127) d = UCD_OTHERCASE(c); else+#endif+ {+#if PCRE2_CODE_UNIT_WIDTH != 8+ if (c > 255) d = c; else+#endif+ d = TABLE_GET(c, cb->fcc, c);+ }++ if (c != d && pptr[2] == d)+ {+ pptr += 3; /* Move on to class end */+ meta = c;+ if ((options & PCRE2_CASELESS) == 0)+ {+ reset_caseful = TRUE;+ options |= PCRE2_CASELESS;+ req_caseopt = REQ_CASELESS;+ }+ goto CLASS_CASELESS_CHAR;+ }+ }+ }++ /* If a non-extended class contains a negative special such as \S, we need+ to flip the negation flag at the end, so that support for characters > 255+ works correctly (they are all included in the class). An extended class may+ need to insert specific matching or non-matching code for wide characters.+ */++ should_flip_negation = match_all_or_no_wide_chars = FALSE;++ /* Extended class (xclass) will be used when characters > 255+ might match. */++#ifdef SUPPORT_WIDE_CHARS+ xclass = FALSE;+ class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */+ class_uchardata_base = class_uchardata; /* Save the start */+#endif++ /* For optimization purposes, we track some properties of the class:+ class_has_8bitchar will be non-zero if the class contains at least one+ character with a code point less than 256; xclass_has_prop will be TRUE if+ Unicode property checks are present in the class. */++ class_has_8bitchar = 0;+#ifdef SUPPORT_WIDE_CHARS+ xclass_has_prop = FALSE;+#endif++ /* Initialize the 256-bit (32-byte) bit map to all zeros. We build the map+ in a temporary bit of memory, in case the class contains fewer than two+ 8-bit characters because in that case the compiled code doesn't use the bit+ map. */++ memset(classbits, 0, 32 * sizeof(uint8_t));++ /* Process items until META_CLASS_END is reached. */++ while ((meta = *(++pptr)) != META_CLASS_END)+ {+ /* Handle POSIX classes such as [:alpha:] etc. */++ if (meta == META_POSIX || meta == META_POSIX_NEG)+ {+ BOOL local_negate = (meta == META_POSIX_NEG);+ int posix_class = *(++pptr);+ int taboffset, tabopt;+ uint8_t pbits[32];++ should_flip_negation = local_negate; /* Note negative special */++ /* If matching is caseless, upper and lower are converted to alpha.+ This relies on the fact that the class table starts with alpha,+ lower, upper as the first 3 entries. */++ if ((options & PCRE2_CASELESS) != 0 && posix_class <= 2)+ posix_class = 0;++ /* When PCRE2_UCP is set, some of the POSIX classes are converted to+ different escape sequences that use Unicode properties \p or \P.+ Others that are not available via \p or \P have to generate+ XCL_PROP/XCL_NOTPROP directly, which is done here. */++#ifdef SUPPORT_UNICODE+ if ((options & PCRE2_UCP) != 0) switch(posix_class)+ {+ case PC_GRAPH:+ case PC_PRINT:+ case PC_PUNCT:+ *class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP;+ *class_uchardata++ = (PCRE2_UCHAR)+ ((posix_class == PC_GRAPH)? PT_PXGRAPH :+ (posix_class == PC_PRINT)? PT_PXPRINT : PT_PXPUNCT);+ *class_uchardata++ = 0;+ xclass_has_prop = TRUE;+ goto CONTINUE_CLASS;++ /* For the other POSIX classes (ascii, xdigit) we are going to+ fall through to the non-UCP case and build a bit map for+ characters with code points less than 256. However, if we are in+ a negated POSIX class, characters with code points greater than+ 255 must either all match or all not match, depending on whether+ the whole class is not or is negated. For example, for+ [[:^ascii:]... they must all match, whereas for [^[:^xdigit:]...+ they must not.++ In the special case where there are no xclass items, this is+ automatically handled by the use of OP_CLASS or OP_NCLASS, but an+ explicit range is needed for OP_XCLASS. Setting a flag here+ causes the range to be generated later when it is known that+ OP_XCLASS is required. In the 8-bit library this is relevant only in+ utf mode, since no wide characters can exist otherwise. */++ default:+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (utf)+#endif+ match_all_or_no_wide_chars |= local_negate;+ break;+ }+#endif /* SUPPORT_UNICODE */++ /* In the non-UCP case, or when UCP makes no difference, we build the+ bit map for the POSIX class in a chunk of local store because we may+ be adding and subtracting from it, and we don't want to subtract bits+ that may be in the main map already. At the end we or the result into+ the bit map that is being built. */++ posix_class *= 3;++ /* Copy in the first table (always present) */++ memcpy(pbits, cbits + posix_class_maps[posix_class],+ 32 * sizeof(uint8_t));++ /* If there is a second table, add or remove it as required. */++ taboffset = posix_class_maps[posix_class + 1];+ tabopt = posix_class_maps[posix_class + 2];++ if (taboffset >= 0)+ {+ if (tabopt >= 0)+ for (i = 0; i < 32; i++) pbits[i] |= cbits[(int)i + taboffset];+ else+ for (i = 0; i < 32; i++) pbits[i] &= ~cbits[(int)i + taboffset];+ }++ /* Now see if we need to remove any special characters. An option+ value of 1 removes vertical space and 2 removes underscore. */++ if (tabopt < 0) tabopt = -tabopt;+ if (tabopt == 1) pbits[1] &= ~0x3c;+ else if (tabopt == 2) pbits[11] &= 0x7f;++ /* Add the POSIX table or its complement into the main table that is+ being built and we are done. */++ if (local_negate)+ for (i = 0; i < 32; i++) classbits[i] |= ~pbits[i];+ else+ for (i = 0; i < 32; i++) classbits[i] |= pbits[i];++ /* Every class contains at least one < 256 character. */++ class_has_8bitchar = 1;+ goto CONTINUE_CLASS; /* End of POSIX handling */+ }++ /* Other than POSIX classes, the only items we should encounter are+ \d-type escapes and literal characters (possibly as ranges). */++ if (meta == META_BIGVALUE)+ {+ meta = *(++pptr);+ goto CLASS_LITERAL;+ }++ /* Any other non-literal must be an escape */++ if (meta >= META_END)+ {+ if (META_CODE(meta) != META_ESCAPE)+ {+#ifdef DEBUG_SHOW_PARSED+ fprintf(stderr, "** Unrecognized parsed pattern item 0x%.8x "+ "in character class\n", meta);+#endif+ *errorcodeptr = ERR89; /* Internal error - unrecognized. */+ return 0;+ }+ escape = META_DATA(meta);++ /* Every class contains at least one < 256 character. */++ class_has_8bitchar++;++ switch(escape)+ {+ case ESC_d:+ for (i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_digit];+ break;++ case ESC_D:+ should_flip_negation = TRUE;+ for (i = 0; i < 32; i++) classbits[i] |= ~cbits[i+cbit_digit];+ break;++ case ESC_w:+ for (i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_word];+ break;++ case ESC_W:+ should_flip_negation = TRUE;+ for (i = 0; i < 32; i++) classbits[i] |= ~cbits[i+cbit_word];+ break;++ /* Perl 5.004 onwards omitted VT from \s, but restored it at Perl+ 5.18. Before PCRE 8.34, we had to preserve the VT bit if it was+ previously set by something earlier in the character class.+ Luckily, the value of CHAR_VT is 0x0b in both ASCII and EBCDIC, so+ we could just adjust the appropriate bit. From PCRE 8.34 we no+ longer treat \s and \S specially. */++ case ESC_s:+ for (i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_space];+ break;++ case ESC_S:+ should_flip_negation = TRUE;+ for (i = 0; i < 32; i++) classbits[i] |= ~cbits[i+cbit_space];+ break;++ /* When adding the horizontal or vertical space lists to a class, or+ their complements, disable PCRE2_CASELESS, because it justs wastes+ time, and in the "not-x" UTF cases can create unwanted duplicates in+ the XCLASS list (provoked by characters that have more than one other+ case and by both cases being in the same "not-x" sublist). */++ case ESC_h:+ (void)add_list_to_class(classbits, &class_uchardata,+ options & ~PCRE2_CASELESS, cb, PRIV(hspace_list), NOTACHAR);+ break;++ case ESC_H:+ (void)add_not_list_to_class(classbits, &class_uchardata,+ options & ~PCRE2_CASELESS, cb, PRIV(hspace_list));+ break;++ case ESC_v:+ (void)add_list_to_class(classbits, &class_uchardata,+ options & ~PCRE2_CASELESS, cb, PRIV(vspace_list), NOTACHAR);+ break;++ case ESC_V:+ (void)add_not_list_to_class(classbits, &class_uchardata,+ options & ~PCRE2_CASELESS, cb, PRIV(vspace_list));+ break;++ /* If Unicode is not supported, \P and \p are not allowed and are+ faulted at parse time, so will never appear here. */++#ifdef SUPPORT_UNICODE+ case ESC_p:+ case ESC_P:+ {+ uint32_t ptype = *(++pptr) >> 16;+ uint32_t pdata = *pptr & 0xffff;+ *class_uchardata++ = (escape == ESC_p)? XCL_PROP : XCL_NOTPROP;+ *class_uchardata++ = ptype;+ *class_uchardata++ = pdata;+ xclass_has_prop = TRUE;+ class_has_8bitchar--; /* Undo! */+ }+ break;+#endif+ }++ goto CONTINUE_CLASS;+ } /* End handling \d-type escapes */++ /* A literal character may be followed by a range meta. At parse time+ there are checks for out-of-order characters, for ranges where the two+ characters are equal, and for hyphens that cannot indicate a range. At+ this point, therefore, no checking is needed. */++ else+ {+ uint32_t c, d;++ CLASS_LITERAL:+ c = d = meta;++ /* Remember if \r or \n were explicitly used */++ if (c == CHAR_CR || c == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;++ /* Process a character range */++ if (pptr[1] == META_RANGE_LITERAL || pptr[1] == META_RANGE_ESCAPED)+ {+#ifdef EBCDIC+ BOOL range_is_literal = (pptr[1] == META_RANGE_LITERAL);+#endif+ pptr += 2;+ d = *pptr;+ if (d == META_BIGVALUE) d = *(++pptr);++ /* Remember an explicit \r or \n, and add the range to the class. */++ if (d == CHAR_CR || d == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;++ /* In an EBCDIC environment, Perl treats alphabetic ranges specially+ because there are holes in the encoding, and simply using the range+ A-Z (for example) would include the characters in the holes. This+ applies only to literal ranges; [\xC1-\xE9] is different to [A-Z]. */++#ifdef EBCDIC+ if (range_is_literal &&+ (cb->ctypes[c] & ctype_letter) != 0 &&+ (cb->ctypes[d] & ctype_letter) != 0 &&+ (c <= CHAR_z) == (d <= CHAR_z))+ {+ uint32_t uc = (d <= CHAR_z)? 0 : 64;+ uint32_t C = c - uc;+ uint32_t D = d - uc;++ if (C <= CHAR_i)+ {+ class_has_8bitchar +=+ add_to_class(classbits, &class_uchardata, options, cb, C + uc,+ ((D < CHAR_i)? D : CHAR_i) + uc);+ C = CHAR_j;+ }++ if (C <= D && C <= CHAR_r)+ {+ class_has_8bitchar +=+ add_to_class(classbits, &class_uchardata, options, cb, C + uc,+ ((D < CHAR_r)? D : CHAR_r) + uc);+ C = CHAR_s;+ }++ if (C <= D)+ {+ class_has_8bitchar +=+ add_to_class(classbits, &class_uchardata, options, cb, C + uc,+ D + uc);+ }+ }+ else+#endif+ /* Not an EBCDIC special range */++ class_has_8bitchar +=+ add_to_class(classbits, &class_uchardata, options, cb, c, d);+ goto CONTINUE_CLASS; /* Go get the next char in the class */+ } /* End of range handling */+++ /* Handle a single character. */++ class_has_8bitchar +=+ add_to_class(classbits, &class_uchardata, options, cb, meta, meta);+ }++ /* Continue to the next item in the class. */++ CONTINUE_CLASS:++#ifdef SUPPORT_WIDE_CHARS+ /* If any wide characters or Unicode properties have been encountered,+ set xclass = TRUE. Then, in the pre-compile phase, accumulate the length+ of the extra data and reset the pointer. This is so that very large+ classes that contain a zillion wide characters or Unicode property tests+ do not overwrite the workspace (which is on the stack). */++ if (class_uchardata > class_uchardata_base)+ {+ xclass = TRUE;+ if (lengthptr != NULL)+ {+ *lengthptr += class_uchardata - class_uchardata_base;+ class_uchardata = class_uchardata_base;+ }+ }+#endif++ continue; /* Needed to avoid error when not supporting wide chars */+ } /* End of main class-processing loop */++ /* If this class is the first thing in the branch, there can be no first+ char setting, whatever the repeat count. Any reqcu setting must remain+ unchanged after any kind of repeat. */++ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;++ /* If there are characters with values > 255, or Unicode property settings+ (\p or \P), we have to compile an extended class, with its own opcode,+ unless there were no property settings and there was a negated special such+ as \S in the class, and PCRE2_UCP is not set, because in that case all+ characters > 255 are in or not in the class, so any that were explicitly+ given as well can be ignored.++ In the UCP case, if certain negated POSIX classes ([:^ascii:] or+ [^:xdigit:]) were present in a class, we either have to match or not match+ all wide characters (depending on whether the whole class is or is not+ negated). This requirement is indicated by match_all_or_no_wide_chars being+ true. We do this by including an explicit range, which works in both cases.+ This applies only in UTF and 16-bit and 32-bit non-UTF modes, since there+ cannot be any wide characters in 8-bit non-UTF mode.++ When there *are* properties in a positive UTF-8 or any 16-bit or 32_bit+ class where \S etc is present without PCRE2_UCP, causing an extended class+ to be compiled, we make sure that all characters > 255 are included by+ forcing match_all_or_no_wide_chars to be true.++ If, when generating an xclass, there are no characters < 256, we can omit+ the bitmap in the actual compiled code. */++#ifdef SUPPORT_WIDE_CHARS /* Defined for 16/32 bits, or 8-bit with Unicode */+ if (xclass && (+#ifdef SUPPORT_UNICODE+ (options & PCRE2_UCP) != 0 ||+#endif+ xclass_has_prop || !should_flip_negation))+ {+ if (match_all_or_no_wide_chars || (+#if PCRE2_CODE_UNIT_WIDTH == 8+ utf &&+#endif+ should_flip_negation && !negate_class && (options & PCRE2_UCP) == 0))+ {+ *class_uchardata++ = XCL_RANGE;+ if (utf) /* Will always be utf in the 8-bit library */+ {+ class_uchardata += PRIV(ord2utf)(0x100, class_uchardata);+ class_uchardata += PRIV(ord2utf)(MAX_UTF_CODE_POINT, class_uchardata);+ }+ else /* Can only happen for the 16-bit & 32-bit libraries */+ {+#if PCRE2_CODE_UNIT_WIDTH == 16+ *class_uchardata++ = 0x100;+ *class_uchardata++ = 0xffffu;+#elif PCRE2_CODE_UNIT_WIDTH == 32+ *class_uchardata++ = 0x100;+ *class_uchardata++ = 0xffffffffu;+#endif+ }+ }+ *class_uchardata++ = XCL_END; /* Marks the end of extra data */+ *code++ = OP_XCLASS;+ code += LINK_SIZE;+ *code = negate_class? XCL_NOT:0;+ if (xclass_has_prop) *code |= XCL_HASPROP;++ /* If the map is required, move up the extra data to make room for it;+ otherwise just move the code pointer to the end of the extra data. */++ if (class_has_8bitchar > 0)+ {+ *code++ |= XCL_MAP;+ (void)memmove(code + (32 / sizeof(PCRE2_UCHAR)), code,+ CU2BYTES(class_uchardata - code));+ if (negate_class && !xclass_has_prop)+ {+ /* Using 255 ^ instead of ~ avoids clang sanitize warning. */+ for (i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];+ }+ memcpy(code, classbits, 32);+ code = class_uchardata + (32 / sizeof(PCRE2_UCHAR));+ }+ else code = class_uchardata;++ /* Now fill in the complete length of the item */++ PUT(previous, 1, (int)(code - previous));+ break; /* End of class handling */+ }+#endif /* SUPPORT_WIDE_CHARS */++ /* If there are no characters > 255, or they are all to be included or+ excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the+ whole class was negated and whether there were negative specials such as \S+ (non-UCP) in the class. Then copy the 32-byte map into the code vector,+ negating it if necessary. */++ *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS;+ if (lengthptr == NULL) /* Save time in the pre-compile phase */+ {+ if (negate_class)+ {+ /* Using 255 ^ instead of ~ avoids clang sanitize warning. */+ for (i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];+ }+ memcpy(code, classbits, 32);+ }+ code += 32 / sizeof(PCRE2_UCHAR);+ break; /* End of class processing */+++ /* ===================================================================*/+ /* Deal with (*VERB)s. */++ /* Check for open captures before ACCEPT and close those that are within+ the same assertion level, also converting ACCEPT to ASSERT_ACCEPT in an+ assertion. In the first pass, just accumulate the length required;+ otherwise hitting (*ACCEPT) inside many nested parentheses can cause+ workspace overflow. Do not set firstcu after *ACCEPT. */++ case META_ACCEPT:+ cb->had_accept = had_accept = TRUE;+ for (oc = cb->open_caps;+ oc != NULL && oc->assert_depth >= cb->assert_depth;+ oc = oc->next)+ {+ if (lengthptr != NULL)+ {+ *lengthptr += CU2BYTES(1) + IMM2_SIZE;+ }+ else+ {+ *code++ = OP_CLOSE;+ PUT2INC(code, 0, oc->number);+ }+ }+ *code++ = (cb->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ break;++ case META_PRUNE:+ case META_SKIP:+ cb->had_pruneorskip = TRUE;+ /* Fall through */+ case META_COMMIT:+ case META_FAIL:+ *code++ = verbops[(meta - META_MARK) >> 16];+ break;++ case META_THEN:+ cb->external_flags |= PCRE2_HASTHEN;+ *code++ = OP_THEN;+ break;++ /* Handle verbs with arguments. Arguments can be very long, especially in+ 16- and 32-bit modes, and can overflow the workspace in the first pass.+ However, the argument length is constrained to be small enough to fit in+ one code unit. This check happens in parse_regex(). In the first pass,+ instead of putting the argument into memory, we just update the length+ counter and set up an empty argument. */++ case META_THEN_ARG:+ cb->external_flags |= PCRE2_HASTHEN;+ goto VERB_ARG;++ case META_PRUNE_ARG:+ case META_SKIP_ARG:+ cb->had_pruneorskip = TRUE;+ /* Fall through */+ case META_MARK:+ case META_COMMIT_ARG:+ VERB_ARG:+ *code++ = verbops[(meta - META_MARK) >> 16];+ /* The length is in characters. */+ verbarglen = *(++pptr);+ verbculen = 0;+ tempcode = code++;+ for (i = 0; i < (int)verbarglen; i++)+ {+ meta = *(++pptr);+#ifdef SUPPORT_UNICODE+ if (utf) mclength = PRIV(ord2utf)(meta, mcbuffer); else+#endif+ {+ mclength = 1;+ mcbuffer[0] = meta;+ }+ if (lengthptr != NULL) *lengthptr += mclength; else+ {+ memcpy(code, mcbuffer, CU2BYTES(mclength));+ code += mclength;+ verbculen += mclength;+ }+ }++ *tempcode = verbculen; /* Fill in the code unit length */+ *code++ = 0; /* Terminating zero */+ break;+++ /* ===================================================================*/+ /* Handle options change. The new setting must be passed back for use in+ subsequent branches. Reset the greedy defaults and the case value for+ firstcu and reqcu. */++ case META_OPTIONS:+ *optionsptr = options = *(++pptr);+ greedy_default = ((options & PCRE2_UNGREEDY) != 0);+ greedy_non_default = greedy_default ^ 1;+ req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS : 0;+ break;+++ /* ===================================================================*/+ /* Handle conditional subpatterns. The case of (?(Rdigits) is ambiguous+ because it could be a numerical check on recursion, or a name check on a+ group's being set. The pre-pass sets up META_COND_RNUMBER as a name so that+ we can handle it either way. We first try for a name; if not found, process+ the number. */++ case META_COND_RNUMBER: /* (?(Rdigits) */+ case META_COND_NAME: /* (?(name) or (?'name') or ?(<name>) */+ case META_COND_RNAME: /* (?(R&name) - test for recursion */+ bravalue = OP_COND;+ {+ int count, index;+ PCRE2_SPTR name;+ named_group *ng = cb->named_groups;+ uint32_t length = *(++pptr);++ GETPLUSOFFSET(offset, pptr);+ name = cb->start_pattern + offset;++ /* In the first pass, the names generated in the pre-pass are available,+ but the main name table has not yet been created. Scan the list of names+ generated in the pre-pass in order to get a number and whether or not+ this name is duplicated. If it is not duplicated, we can handle it as a+ numerical group. */++ for (i = 0; i < cb->names_found; i++, ng++)+ {+ if (length == ng->length &&+ PRIV(strncmp)(name, ng->name, length) == 0)+ {+ if (!ng->isdup)+ {+ code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;+ PUT2(code, 2+LINK_SIZE, ng->number);+ if (ng->number > cb->top_backref) cb->top_backref = ng->number;+ skipunits = 1+IMM2_SIZE;+ goto GROUP_PROCESS_NOTE_EMPTY;+ }+ break; /* Found a duplicated name */+ }+ }++ /* If the name was not found we have a bad reference, unless we are+ dealing with R<digits>, which is treated as a recursion test by number.+ */++ if (i >= cb->names_found)+ {+ groupnumber = 0;+ if (meta == META_COND_RNUMBER)+ {+ for (i = 1; i < (int)length; i++)+ {+ groupnumber = groupnumber * 10 + name[i] - CHAR_0;+ if (groupnumber > MAX_GROUP_NUMBER)+ {+ *errorcodeptr = ERR61;+ cb->erroroffset = offset + i;+ return 0;+ }+ }+ }++ if (meta != META_COND_RNUMBER || groupnumber > cb->bracount)+ {+ *errorcodeptr = ERR15;+ cb->erroroffset = offset;+ return 0;+ }++ /* (?Rdigits) treated as a recursion reference by number. A value of+ zero (which is the result of both (?R) and (?R0)) means "any", and is+ translated into RREF_ANY (which is 0xffff). */++ if (groupnumber == 0) groupnumber = RREF_ANY;+ code[1+LINK_SIZE] = OP_RREF;+ PUT2(code, 2+LINK_SIZE, groupnumber);+ skipunits = 1+IMM2_SIZE;+ goto GROUP_PROCESS_NOTE_EMPTY;+ }++ /* A duplicated name was found. Note that if an R<digits> name is found+ (META_COND_RNUMBER), it is a reference test, not a recursion test. */++ code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;++ /* We have a duplicated name. In the compile pass we have to search the+ main table in order to get the index and count values. */++ count = 0; /* Values for first pass (avoids compiler warning) */+ index = 0;+ if (lengthptr == NULL && !find_dupname_details(name, length, &index,+ &count, errorcodeptr, cb)) return 0;++ /* Add one to the opcode to change CREF/RREF into DNCREF/DNRREF and+ insert appropriate data values. */++ code[1+LINK_SIZE]++;+ skipunits = 1+2*IMM2_SIZE;+ PUT2(code, 2+LINK_SIZE, index);+ PUT2(code, 2+LINK_SIZE+IMM2_SIZE, count);+ }+ goto GROUP_PROCESS_NOTE_EMPTY;++ /* The DEFINE condition is always false. Its internal groups may never+ be called, so matched_char must remain false, hence the jump to+ GROUP_PROCESS rather than GROUP_PROCESS_NOTE_EMPTY. */++ case META_COND_DEFINE:+ bravalue = OP_COND;+ GETPLUSOFFSET(offset, pptr);+ code[1+LINK_SIZE] = OP_DEFINE;+ skipunits = 1;+ goto GROUP_PROCESS;++ /* Conditional test of a group's being set. */++ case META_COND_NUMBER:+ bravalue = OP_COND;+ GETPLUSOFFSET(offset, pptr);+ groupnumber = *(++pptr);+ if (groupnumber > cb->bracount)+ {+ *errorcodeptr = ERR15;+ cb->erroroffset = offset;+ return 0;+ }+ if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;+ offset -= 2; /* Point at initial ( for too many branches error */+ code[1+LINK_SIZE] = OP_CREF;+ skipunits = 1+IMM2_SIZE;+ PUT2(code, 2+LINK_SIZE, groupnumber);+ goto GROUP_PROCESS_NOTE_EMPTY;++ /* Test for the PCRE2 version. */++ case META_COND_VERSION:+ bravalue = OP_COND;+ if (pptr[1] > 0)+ code[1+LINK_SIZE] = ((PCRE2_MAJOR > pptr[2]) ||+ (PCRE2_MAJOR == pptr[2] && PCRE2_MINOR >= pptr[3]))?+ OP_TRUE : OP_FALSE;+ else+ code[1+LINK_SIZE] = (PCRE2_MAJOR == pptr[2] && PCRE2_MINOR == pptr[3])?+ OP_TRUE : OP_FALSE;+ skipunits = 1;+ pptr += 3;+ goto GROUP_PROCESS_NOTE_EMPTY;++ /* The condition is an assertion, possibly preceded by a callout. */++ case META_COND_ASSERT:+ bravalue = OP_COND;+ goto GROUP_PROCESS_NOTE_EMPTY;+++ /* ===================================================================*/+ /* Handle all kinds of nested bracketed groups. The non-capturing,+ non-conditional cases are here; others come to GROUP_PROCESS via goto. */++ case META_LOOKAHEAD:+ bravalue = OP_ASSERT;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;++ case META_LOOKAHEAD_NA:+ bravalue = OP_ASSERT_NA;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;++ /* Optimize (?!) to (*FAIL) unless it is quantified - which is a weird+ thing to do, but Perl allows all assertions to be quantified, and when+ they contain capturing parentheses there may be a potential use for+ this feature. Not that that applies to a quantified (?!) but we allow+ it for uniformity. */++ case META_LOOKAHEADNOT:+ if (pptr[1] == META_KET &&+ (pptr[2] < META_ASTERISK || pptr[2] > META_MINMAX_QUERY))+ {+ *code++ = OP_FAIL;+ pptr++;+ }+ else+ {+ bravalue = OP_ASSERT_NOT;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;+ }+ break;++ case META_LOOKBEHIND:+ bravalue = OP_ASSERTBACK;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;++ case META_LOOKBEHINDNOT:+ bravalue = OP_ASSERTBACK_NOT;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;++ case META_LOOKBEHIND_NA:+ bravalue = OP_ASSERTBACK_NA;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;++ case META_ATOMIC:+ bravalue = OP_ONCE;+ goto GROUP_PROCESS_NOTE_EMPTY;++ case META_SCRIPT_RUN:+ bravalue = OP_SCRIPT_RUN;+ goto GROUP_PROCESS_NOTE_EMPTY;++ case META_NOCAPTURE:+ bravalue = OP_BRA;+ /* Fall through */++ /* Process nested bracketed regex. The nesting depth is maintained for the+ benefit of the stackguard function. The test for too deep nesting is now+ done in parse_regex(). Assertion and DEFINE groups come to GROUP_PROCESS;+ others come to GROUP_PROCESS_NOTE_EMPTY, to indicate that we need to take+ note of whether or not they may match an empty string. */++ GROUP_PROCESS_NOTE_EMPTY:+ note_group_empty = TRUE;++ GROUP_PROCESS:+ cb->parens_depth += 1;+ *code = bravalue;+ pptr++;+ tempcode = code;+ tempreqvary = cb->req_varyopt; /* Save value before group */+ length_prevgroup = 0; /* Initialize for pre-compile phase */++ if ((group_return =+ compile_regex(+ options, /* The option state */+ &tempcode, /* Where to put code (updated) */+ &pptr, /* Input pointer (updated) */+ errorcodeptr, /* Where to put an error message */+ skipunits, /* Skip over bracket number */+ &subfirstcu, /* For possible first char */+ &subfirstcuflags,+ &subreqcu, /* For possible last char */+ &subreqcuflags,+ bcptr, /* Current branch chain */+ cb, /* Compile data block */+ (lengthptr == NULL)? NULL : /* Actual compile phase */+ &length_prevgroup /* Pre-compile phase */+ )) == 0)+ return 0; /* Error */++ cb->parens_depth -= 1;++ /* If that was a non-conditional significant group (not an assertion, not a+ DEFINE) that matches at least one character, then the current item matches+ a character. Conditionals are handled below. */++ if (note_group_empty && bravalue != OP_COND && group_return > 0)+ matched_char = TRUE;++ /* If we've just compiled an assertion, pop the assert depth. */++ if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NA)+ cb->assert_depth -= 1;++ /* At the end of compiling, code is still pointing to the start of the+ group, while tempcode has been updated to point past the end of the group.+ The parsed pattern pointer (pptr) is on the closing META_KET.++ If this is a conditional bracket, check that there are no more than+ two branches in the group, or just one if it's a DEFINE group. We do this+ in the real compile phase, not in the pre-pass, where the whole group may+ not be available. */++ if (bravalue == OP_COND && lengthptr == NULL)+ {+ PCRE2_UCHAR *tc = code;+ int condcount = 0;++ do {+ condcount++;+ tc += GET(tc,1);+ }+ while (*tc != OP_KET);++ /* A DEFINE group is never obeyed inline (the "condition" is always+ false). It must have only one branch. Having checked this, change the+ opcode to OP_FALSE. */++ if (code[LINK_SIZE+1] == OP_DEFINE)+ {+ if (condcount > 1)+ {+ cb->erroroffset = offset;+ *errorcodeptr = ERR54;+ return 0;+ }+ code[LINK_SIZE+1] = OP_FALSE;+ bravalue = OP_DEFINE; /* A flag to suppress char handling below */+ }++ /* A "normal" conditional group. If there is just one branch, we must not+ make use of its firstcu or reqcu, because this is equivalent to an+ empty second branch. Also, it may match an empty string. If there are two+ branches, this item must match a character if the group must. */++ else+ {+ if (condcount > 2)+ {+ cb->erroroffset = offset;+ *errorcodeptr = ERR27;+ return 0;+ }+ if (condcount == 1) subfirstcuflags = subreqcuflags = REQ_NONE;+ else if (group_return > 0) matched_char = TRUE;+ }+ }++ /* In the pre-compile phase, update the length by the length of the group,+ less the brackets at either end. Then reduce the compiled code to just a+ set of non-capturing brackets so that it doesn't use much memory if it is+ duplicated by a quantifier.*/++ if (lengthptr != NULL)+ {+ if (OFLOW_MAX - *lengthptr < length_prevgroup - 2 - 2*LINK_SIZE)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ *lengthptr += length_prevgroup - 2 - 2*LINK_SIZE;+ code++; /* This already contains bravalue */+ PUTINC(code, 0, 1 + LINK_SIZE);+ *code++ = OP_KET;+ PUTINC(code, 0, 1 + LINK_SIZE);+ break; /* No need to waste time with special character handling */+ }++ /* Otherwise update the main code pointer to the end of the group. */++ code = tempcode;++ /* For a DEFINE group, required and first character settings are not+ relevant. */++ if (bravalue == OP_DEFINE) break;++ /* Handle updating of the required and first code units for other types of+ group. Update for normal brackets of all kinds, and conditions with two+ branches (see code above). If the bracket is followed by a quantifier with+ zero repeat, we have to back off. Hence the definition of zeroreqcu and+ zerofirstcu outside the main loop so that they can be accessed for the back+ off. */++ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ groupsetfirstcu = FALSE;++ if (bravalue >= OP_ONCE) /* Not an assertion */+ {+ /* If we have not yet set a firstcu in this branch, take it from the+ subpattern, remembering that it was set here so that a repeat of more+ than one can replicate it as reqcu if necessary. If the subpattern has+ no firstcu, set "none" for the whole branch. In both cases, a zero+ repeat forces firstcu to "none". */++ if (firstcuflags == REQ_UNSET && subfirstcuflags != REQ_UNSET)+ {+ if (subfirstcuflags >= 0)+ {+ firstcu = subfirstcu;+ firstcuflags = subfirstcuflags;+ groupsetfirstcu = TRUE;+ }+ else firstcuflags = REQ_NONE;+ zerofirstcuflags = REQ_NONE;+ }++ /* If firstcu was previously set, convert the subpattern's firstcu+ into reqcu if there wasn't one, using the vary flag that was in+ existence beforehand. */++ else if (subfirstcuflags >= 0 && subreqcuflags < 0)+ {+ subreqcu = subfirstcu;+ subreqcuflags = subfirstcuflags | tempreqvary;+ }++ /* If the subpattern set a required code unit (or set a first code unit+ that isn't really the first code unit - see above), set it. */++ if (subreqcuflags >= 0)+ {+ reqcu = subreqcu;+ reqcuflags = subreqcuflags;+ }+ }++ /* For a forward assertion, we take the reqcu, if set, provided that the+ group has also set a firstcu. This can be helpful if the pattern that+ follows the assertion doesn't set a different char. For example, it's+ useful for /(?=abcde).+/. We can't set firstcu for an assertion, however+ because it leads to incorrect effect for patterns such as /(?=a)a.+/ when+ the "real" "a" would then become a reqcu instead of a firstcu. This is+ overcome by a scan at the end if there's no firstcu, looking for an+ asserted first char. A similar effect for patterns like /(?=.*X)X$/ means+ we must only take the reqcu when the group also set a firstcu. Otherwise,+ in that example, 'X' ends up set for both. */++ else if ((bravalue == OP_ASSERT || bravalue == OP_ASSERT_NA) &&+ subreqcuflags >= 0 && subfirstcuflags >= 0)+ {+ reqcu = subreqcu;+ reqcuflags = subreqcuflags;+ }++ break; /* End of nested group handling */+++ /* ===================================================================*/+ /* Handle named backreferences and recursions. */++ case META_BACKREF_BYNAME:+ case META_RECURSE_BYNAME:+ {+ int count, index;+ PCRE2_SPTR name;+ BOOL is_dupname = FALSE;+ named_group *ng = cb->named_groups;+ uint32_t length = *(++pptr);++ GETPLUSOFFSET(offset, pptr);+ name = cb->start_pattern + offset;++ /* In the first pass, the names generated in the pre-pass are available,+ but the main name table has not yet been created. Scan the list of names+ generated in the pre-pass in order to get a number and whether or not+ this name is duplicated. */++ groupnumber = 0;+ for (i = 0; i < cb->names_found; i++, ng++)+ {+ if (length == ng->length &&+ PRIV(strncmp)(name, ng->name, length) == 0)+ {+ is_dupname = ng->isdup;+ groupnumber = ng->number;++ /* For a recursion, that's all that is needed. We can now go to+ the code that handles numerical recursion, applying it to the first+ group with the given name. */++ if (meta == META_RECURSE_BYNAME)+ {+ meta_arg = groupnumber;+ goto HANDLE_NUMERICAL_RECURSION;+ }++ /* For a back reference, update the back reference map and the+ maximum back reference. */++ cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;+ if (groupnumber > cb->top_backref)+ cb->top_backref = groupnumber;+ }+ }++ /* If the name was not found we have a bad reference. */++ if (groupnumber == 0)+ {+ *errorcodeptr = ERR15;+ cb->erroroffset = offset;+ return 0;+ }++ /* If a back reference name is not duplicated, we can handle it as+ a numerical reference. */++ if (!is_dupname)+ {+ meta_arg = groupnumber;+ goto HANDLE_SINGLE_REFERENCE;+ }++ /* If a back reference name is duplicated, we generate a different+ opcode to a numerical back reference. In the second pass we must+ search for the index and count in the final name table. */++ count = 0; /* Values for first pass (avoids compiler warning) */+ index = 0;+ if (lengthptr == NULL && !find_dupname_details(name, length, &index,+ &count, errorcodeptr, cb)) return 0;++ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_DNREFI : OP_DNREF;+ PUT2INC(code, 0, index);+ PUT2INC(code, 0, count);+ }+ break;+++ /* ===================================================================*/+ /* Handle a numerical callout. */++ case META_CALLOUT_NUMBER:+ code[0] = OP_CALLOUT;+ PUT(code, 1, pptr[1]); /* Offset to next pattern item */+ PUT(code, 1 + LINK_SIZE, pptr[2]); /* Length of next pattern item */+ code[1 + 2*LINK_SIZE] = pptr[3];+ pptr += 3;+ code += PRIV(OP_lengths)[OP_CALLOUT];+ break;+++ /* ===================================================================*/+ /* Handle a callout with a string argument. In the pre-pass we just compute+ the length without generating anything. The length in pptr[3] includes both+ delimiters; in the actual compile only the first one is copied, but a+ terminating zero is added. Any doubled delimiters within the string make+ this an overestimate, but it is not worth bothering about. */++ case META_CALLOUT_STRING:+ if (lengthptr != NULL)+ {+ *lengthptr += pptr[3] + (1 + 4*LINK_SIZE);+ pptr += 3;+ SKIPOFFSET(pptr);+ }++ /* In the real compile we can copy the string. The starting delimiter is+ included so that the client can discover it if they want. We also pass the+ start offset to help a script language give better error messages. */++ else+ {+ PCRE2_SPTR pp;+ uint32_t delimiter;+ uint32_t length = pptr[3];+ PCRE2_UCHAR *callout_string = code + (1 + 4*LINK_SIZE);++ code[0] = OP_CALLOUT_STR;+ PUT(code, 1, pptr[1]); /* Offset to next pattern item */+ PUT(code, 1 + LINK_SIZE, pptr[2]); /* Length of next pattern item */++ pptr += 3;+ GETPLUSOFFSET(offset, pptr); /* Offset to string in pattern */+ pp = cb->start_pattern + offset;+ delimiter = *callout_string++ = *pp++;+ if (delimiter == CHAR_LEFT_CURLY_BRACKET)+ delimiter = CHAR_RIGHT_CURLY_BRACKET;+ PUT(code, 1 + 3*LINK_SIZE, (int)(offset + 1)); /* One after delimiter */++ /* The syntax of the pattern was checked in the parsing scan. The length+ includes both delimiters, but we have passed the opening one just above,+ so we reduce length before testing it. The test is for > 1 because we do+ not want to copy the final delimiter. This also ensures that pp[1] is+ accessible. */++ while (--length > 1)+ {+ if (*pp == delimiter && pp[1] == delimiter)+ {+ *callout_string++ = delimiter;+ pp += 2;+ length--;+ }+ else *callout_string++ = *pp++;+ }+ *callout_string++ = CHAR_NUL;++ /* Set the length of the entire item, the advance to its end. */++ PUT(code, 1 + 2*LINK_SIZE, (int)(callout_string - code));+ code = callout_string;+ }+ break;+++ /* ===================================================================*/+ /* Handle repetition. The different types are all sorted out in the parsing+ pass. */++ case META_MINMAX_PLUS:+ case META_MINMAX_QUERY:+ case META_MINMAX:+ repeat_min = *(++pptr);+ repeat_max = *(++pptr);+ goto REPEAT;++ case META_ASTERISK:+ case META_ASTERISK_PLUS:+ case META_ASTERISK_QUERY:+ repeat_min = 0;+ repeat_max = REPEAT_UNLIMITED;+ goto REPEAT;++ case META_PLUS:+ case META_PLUS_PLUS:+ case META_PLUS_QUERY:+ repeat_min = 1;+ repeat_max = REPEAT_UNLIMITED;+ goto REPEAT;++ case META_QUERY:+ case META_QUERY_PLUS:+ case META_QUERY_QUERY:+ repeat_min = 0;+ repeat_max = 1;++ REPEAT:+ if (previous_matched_char && repeat_min > 0) matched_char = TRUE;++ /* Remember whether this is a variable length repeat, and default to+ single-char opcodes. */++ reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY;+ op_type = 0;++ /* Adjust first and required code units for a zero repeat. */++ if (repeat_min == 0)+ {+ firstcu = zerofirstcu;+ firstcuflags = zerofirstcuflags;+ reqcu = zeroreqcu;+ reqcuflags = zeroreqcuflags;+ }++ /* Note the greediness and possessiveness. */++ switch (meta)+ {+ case META_MINMAX_PLUS:+ case META_ASTERISK_PLUS:+ case META_PLUS_PLUS:+ case META_QUERY_PLUS:+ repeat_type = 0; /* Force greedy */+ possessive_quantifier = TRUE;+ break;++ case META_MINMAX_QUERY:+ case META_ASTERISK_QUERY:+ case META_PLUS_QUERY:+ case META_QUERY_QUERY:+ repeat_type = greedy_non_default;+ possessive_quantifier = FALSE;+ break;++ default:+ repeat_type = greedy_default;+ possessive_quantifier = FALSE;+ break;+ }++ /* Save start of previous item, in case we have to move it up in order to+ insert something before it, and remember what it was. */++ tempcode = previous;+ op_previous = *previous;++ /* Now handle repetition for the different types of item. If the repeat+ minimum and the repeat maximum are both 1, we can ignore the quantifier for+ non-parenthesized items, as they have only one alternative. For anything in+ parentheses, we must not ignore if {1} is possessive. */++ switch (op_previous)+ {+ /* If previous was a character or negated character match, abolish the+ item and generate a repeat item instead. If a char item has a minimum of+ more than one, ensure that it is set in reqcu - it might not be if a+ sequence such as x{3} is the first thing in a branch because the x will+ have gone into firstcu instead. */++ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;+ op_type = chartypeoffset[op_previous - OP_CHAR];++ /* Deal with UTF characters that take up more than one code unit. */++#ifdef MAYBE_UTF_MULTI+ if (utf && NOT_FIRSTCU(code[-1]))+ {+ PCRE2_UCHAR *lastchar = code - 1;+ BACKCHAR(lastchar);+ mclength = (uint32_t)(code - lastchar); /* Length of UTF character */+ memcpy(mcbuffer, lastchar, CU2BYTES(mclength)); /* Save the char */+ }+ else+#endif /* MAYBE_UTF_MULTI */++ /* Handle the case of a single code unit - either with no UTF support, or+ with UTF disabled, or for a single-code-unit UTF character. */+ {+ mcbuffer[0] = code[-1];+ mclength = 1;+ if (op_previous <= OP_CHARI && repeat_min > 1)+ {+ reqcu = mcbuffer[0];+ reqcuflags = req_caseopt | cb->req_varyopt;+ }+ }+ goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */++ /* If previous was a character class or a back reference, we put the+ repeat stuff after it, but just skip the item if the repeat was {0,0}. */++#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+#endif+ case OP_CLASS:+ case OP_NCLASS:+ case OP_REF:+ case OP_REFI:+ case OP_DNREF:+ case OP_DNREFI:++ if (repeat_max == 0)+ {+ code = previous;+ goto END_REPEAT;+ }+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;++ if (repeat_min == 0 && repeat_max == REPEAT_UNLIMITED)+ *code++ = OP_CRSTAR + repeat_type;+ else if (repeat_min == 1 && repeat_max == REPEAT_UNLIMITED)+ *code++ = OP_CRPLUS + repeat_type;+ else if (repeat_min == 0 && repeat_max == 1)+ *code++ = OP_CRQUERY + repeat_type;+ else+ {+ *code++ = OP_CRRANGE + repeat_type;+ PUT2INC(code, 0, repeat_min);+ if (repeat_max == REPEAT_UNLIMITED) repeat_max = 0; /* 2-byte encoding for max */+ PUT2INC(code, 0, repeat_max);+ }+ break;++ /* If previous is OP_FAIL, it was generated by an empty class []+ (PCRE2_ALLOW_EMPTY_CLASS is set). The other ways in which OP_FAIL can be+ generated, that is by (*FAIL) or (?!), disallow a quantifier at parse+ time. We can just ignore this repeat. */++ case OP_FAIL:+ goto END_REPEAT;++ /* Prior to 10.30, repeated recursions were wrapped in OP_ONCE brackets+ because pcre2_match() could not handle backtracking into recursively+ called groups. Now that this backtracking is available, we no longer need+ to do this. However, we still need to replicate recursions as we do for+ groups so as to have independent backtracking points. We can replicate+ for the minimum number of repeats directly. For optional repeats we now+ wrap the recursion in OP_BRA brackets and make use of the bracket+ repetition. */++ case OP_RECURSE:+ if (repeat_max == 1 && repeat_min == 1 && !possessive_quantifier)+ goto END_REPEAT;++ /* Generate unwrapped repeats for a non-zero minimum, except when the+ minimum is 1 and the maximum unlimited, because that can be handled with+ OP_BRA terminated by OP_KETRMAX/MIN. When the maximum is equal to the+ minimum, we just need to generate the appropriate additional copies.+ Otherwise we need to generate one more, to simulate the situation when+ the minimum is zero. */++ if (repeat_min > 0 && (repeat_min != 1 || repeat_max != REPEAT_UNLIMITED))+ {+ int replicate = repeat_min;+ if (repeat_min == repeat_max) replicate--;++ /* In the pre-compile phase, we don't actually do the replication. We+ just adjust the length as if we had. Do some paranoid checks for+ potential integer overflow. The INT64_OR_DOUBLE type is a 64-bit+ integer type when available, otherwise double. */++ if (lengthptr != NULL)+ {+ PCRE2_SIZE delta = replicate*(1 + LINK_SIZE);+ if ((INT64_OR_DOUBLE)replicate*+ (INT64_OR_DOUBLE)(1 + LINK_SIZE) >+ (INT64_OR_DOUBLE)INT_MAX ||+ OFLOW_MAX - *lengthptr < delta)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ *lengthptr += delta;+ }++ else for (i = 0; i < replicate; i++)+ {+ memcpy(code, previous, CU2BYTES(1 + LINK_SIZE));+ previous = code;+ code += 1 + LINK_SIZE;+ }++ /* If the number of repeats is fixed, we are done. Otherwise, adjust+ the counts and fall through. */++ if (repeat_min == repeat_max) break;+ if (repeat_max != REPEAT_UNLIMITED) repeat_max -= repeat_min;+ repeat_min = 0;+ }++ /* Wrap the recursion call in OP_BRA brackets. */++ (void)memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(1 + LINK_SIZE));+ op_previous = *previous = OP_BRA;+ PUT(previous, 1, 2 + 2*LINK_SIZE);+ previous[2 + 2*LINK_SIZE] = OP_KET;+ PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE);+ code += 2 + 2 * LINK_SIZE;+ length_prevgroup = 3 + 3*LINK_SIZE;+ group_return = -1; /* Set "may match empty string" */++ /* Now treat as a repeated OP_BRA. */+ /* Fall through */++ /* If previous was a bracket group, we may have to replicate it in+ certain cases. Note that at this point we can encounter only the "basic"+ bracket opcodes such as BRA and CBRA, as this is the place where they get+ converted into the more special varieties such as BRAPOS and SBRA.+ Originally, PCRE did not allow repetition of assertions, but now it does,+ for Perl compatibility. */++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRA:+ case OP_CBRA:+ case OP_COND:+ {+ int len = (int)(code - previous);+ PCRE2_UCHAR *bralink = NULL;+ PCRE2_UCHAR *brazeroptr = NULL;++ if (repeat_max == 1 && repeat_min == 1 && !possessive_quantifier)+ goto END_REPEAT;++ /* Repeating a DEFINE group (or any group where the condition is always+ FALSE and there is only one branch) is pointless, but Perl allows the+ syntax, so we just ignore the repeat. */++ if (op_previous == OP_COND && previous[LINK_SIZE+1] == OP_FALSE &&+ previous[GET(previous, 1)] != OP_ALT)+ goto END_REPEAT;++ /* Perl allows all assertions to be quantified, and when they contain+ capturing parentheses and/or are optional there are potential uses for+ this feature. PCRE2 used to force the maximum quantifier to 1 on the+ invalid grounds that further repetition was never useful. This was+ always a bit pointless, since an assertion could be wrapped with a+ repeated group to achieve the effect. General repetition is now+ permitted, but if the maximum is unlimited it is set to one more than+ the minimum. */++ if (op_previous < OP_ONCE) /* Assertion */+ {+ if (repeat_max == REPEAT_UNLIMITED) repeat_max = repeat_min + 1;+ }++ /* The case of a zero minimum is special because of the need to stick+ OP_BRAZERO in front of it, and because the group appears once in the+ data, whereas in other cases it appears the minimum number of times. For+ this reason, it is simplest to treat this case separately, as otherwise+ the code gets far too messy. There are several special subcases when the+ minimum is zero. */++ if (repeat_min == 0)+ {+ /* If the maximum is also zero, we used to just omit the group from+ the output altogether, like this:++ ** if (repeat_max == 0)+ ** {+ ** code = previous;+ ** goto END_REPEAT;+ ** }++ However, that fails when a group or a subgroup within it is+ referenced as a subroutine from elsewhere in the pattern, so now we+ stick in OP_SKIPZERO in front of it so that it is skipped on+ execution. As we don't have a list of which groups are referenced, we+ cannot do this selectively.++ If the maximum is 1 or unlimited, we just have to stick in the+ BRAZERO and do no more at this point. */++ if (repeat_max <= 1 || repeat_max == REPEAT_UNLIMITED)+ {+ (void)memmove(previous + 1, previous, CU2BYTES(len));+ code++;+ if (repeat_max == 0)+ {+ *previous++ = OP_SKIPZERO;+ goto END_REPEAT;+ }+ brazeroptr = previous; /* Save for possessive optimizing */+ *previous++ = OP_BRAZERO + repeat_type;+ }++ /* If the maximum is greater than 1 and limited, we have to replicate+ in a nested fashion, sticking OP_BRAZERO before each set of brackets.+ The first one has to be handled carefully because it's the original+ copy, which has to be moved up. The remainder can be handled by code+ that is common with the non-zero minimum case below. We have to+ adjust the value or repeat_max, since one less copy is required. */++ else+ {+ int linkoffset;+ (void)memmove(previous + 2 + LINK_SIZE, previous, CU2BYTES(len));+ code += 2 + LINK_SIZE;+ *previous++ = OP_BRAZERO + repeat_type;+ *previous++ = OP_BRA;++ /* We chain together the bracket link offset fields that have to be+ filled in later when the ends of the brackets are reached. */++ linkoffset = (bralink == NULL)? 0 : (int)(previous - bralink);+ bralink = previous;+ PUTINC(previous, 0, linkoffset);+ }++ if (repeat_max != REPEAT_UNLIMITED) repeat_max--;+ }++ /* If the minimum is greater than zero, replicate the group as many+ times as necessary, and adjust the maximum to the number of subsequent+ copies that we need. */++ else+ {+ if (repeat_min > 1)+ {+ /* In the pre-compile phase, we don't actually do the replication.+ We just adjust the length as if we had. Do some paranoid checks for+ potential integer overflow. The INT64_OR_DOUBLE type is a 64-bit+ integer type when available, otherwise double. */++ if (lengthptr != NULL)+ {+ PCRE2_SIZE delta = (repeat_min - 1)*length_prevgroup;+ if ((INT64_OR_DOUBLE)(repeat_min - 1)*+ (INT64_OR_DOUBLE)length_prevgroup >+ (INT64_OR_DOUBLE)INT_MAX ||+ OFLOW_MAX - *lengthptr < delta)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ *lengthptr += delta;+ }++ /* This is compiling for real. If there is a set first code unit+ for the group, and we have not yet set a "required code unit", set+ it. */++ else+ {+ if (groupsetfirstcu && reqcuflags < 0)+ {+ reqcu = firstcu;+ reqcuflags = firstcuflags;+ }+ for (i = 1; (uint32_t)i < repeat_min; i++)+ {+ memcpy(code, previous, CU2BYTES(len));+ code += len;+ }+ }+ }++ if (repeat_max != REPEAT_UNLIMITED) repeat_max -= repeat_min;+ }++ /* This code is common to both the zero and non-zero minimum cases. If+ the maximum is limited, it replicates the group in a nested fashion,+ remembering the bracket starts on a stack. In the case of a zero+ minimum, the first one was set up above. In all cases the repeat_max+ now specifies the number of additional copies needed. Again, we must+ remember to replicate entries on the forward reference list. */++ if (repeat_max != REPEAT_UNLIMITED)+ {+ /* In the pre-compile phase, we don't actually do the replication. We+ just adjust the length as if we had. For each repetition we must add+ 1 to the length for BRAZERO and for all but the last repetition we+ must add 2 + 2*LINKSIZE to allow for the nesting that occurs. Do some+ paranoid checks to avoid integer overflow. The INT64_OR_DOUBLE type+ is a 64-bit integer type when available, otherwise double. */++ if (lengthptr != NULL && repeat_max > 0)+ {+ PCRE2_SIZE delta = repeat_max*(length_prevgroup + 1 + 2 + 2*LINK_SIZE) -+ 2 - 2*LINK_SIZE; /* Last one doesn't nest */+ if ((INT64_OR_DOUBLE)repeat_max *+ (INT64_OR_DOUBLE)(length_prevgroup + 1 + 2 + 2*LINK_SIZE)+ > (INT64_OR_DOUBLE)INT_MAX ||+ OFLOW_MAX - *lengthptr < delta)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ *lengthptr += delta;+ }++ /* This is compiling for real */++ else for (i = repeat_max - 1; i >= 0; i--)+ {+ *code++ = OP_BRAZERO + repeat_type;++ /* All but the final copy start a new nesting, maintaining the+ chain of brackets outstanding. */++ if (i != 0)+ {+ int linkoffset;+ *code++ = OP_BRA;+ linkoffset = (bralink == NULL)? 0 : (int)(code - bralink);+ bralink = code;+ PUTINC(code, 0, linkoffset);+ }++ memcpy(code, previous, CU2BYTES(len));+ code += len;+ }++ /* Now chain through the pending brackets, and fill in their length+ fields (which are holding the chain links pro tem). */++ while (bralink != NULL)+ {+ int oldlinkoffset;+ int linkoffset = (int)(code - bralink + 1);+ PCRE2_UCHAR *bra = code - linkoffset;+ oldlinkoffset = GET(bra, 1);+ bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;+ *code++ = OP_KET;+ PUTINC(code, 0, linkoffset);+ PUT(bra, 1, linkoffset);+ }+ }++ /* If the maximum is unlimited, set a repeater in the final copy. For+ SCRIPT_RUN and ONCE brackets, that's all we need to do. However,+ possessively repeated ONCE brackets can be converted into non-capturing+ brackets, as the behaviour of (?:xx)++ is the same as (?>xx)++ and this+ saves having to deal with possessive ONCEs specially.++ Otherwise, when we are doing the actual compile phase, check to see+ whether this group is one that could match an empty string. If so,+ convert the initial operator to the S form (e.g. OP_BRA -> OP_SBRA) so+ that runtime checking can be done. [This check is also applied to ONCE+ and SCRIPT_RUN groups at runtime, but in a different way.]++ Then, if the quantifier was possessive and the bracket is not a+ conditional, we convert the BRA code to the POS form, and the KET code+ to KETRPOS. (It turns out to be convenient at runtime to detect this+ kind of subpattern at both the start and at the end.) The use of+ special opcodes makes it possible to reduce greatly the stack usage in+ pcre2_match(). If the group is preceded by OP_BRAZERO, convert this to+ OP_BRAPOSZERO.++ Then, if the minimum number of matches is 1 or 0, cancel the possessive+ flag so that the default action below, of wrapping everything inside+ atomic brackets, does not happen. When the minimum is greater than 1,+ there will be earlier copies of the group, and so we still have to wrap+ the whole thing. */++ else+ {+ PCRE2_UCHAR *ketcode = code - 1 - LINK_SIZE;+ PCRE2_UCHAR *bracode = ketcode - GET(ketcode, 1);++ /* Convert possessive ONCE brackets to non-capturing */++ if (*bracode == OP_ONCE && possessive_quantifier) *bracode = OP_BRA;++ /* For non-possessive ONCE and for SCRIPT_RUN brackets, all we need+ to do is to set the KET. */++ if (*bracode == OP_ONCE || *bracode == OP_SCRIPT_RUN)+ *ketcode = OP_KETRMAX + repeat_type;++ /* Handle non-SCRIPT_RUN and non-ONCE brackets and possessive ONCEs+ (which have been converted to non-capturing above). */++ else+ {+ /* In the compile phase, adjust the opcode if the group can match+ an empty string. For a conditional group with only one branch, the+ value of group_return will not show "could be empty", so we must+ check that separately. */++ if (lengthptr == NULL)+ {+ if (group_return < 0) *bracode += OP_SBRA - OP_BRA;+ if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT)+ *bracode = OP_SCOND;+ }++ /* Handle possessive quantifiers. */++ if (possessive_quantifier)+ {+ /* For COND brackets, we wrap the whole thing in a possessively+ repeated non-capturing bracket, because we have not invented POS+ versions of the COND opcodes. */++ if (*bracode == OP_COND || *bracode == OP_SCOND)+ {+ int nlen = (int)(code - bracode);+ (void)memmove(bracode + 1 + LINK_SIZE, bracode, CU2BYTES(nlen));+ code += 1 + LINK_SIZE;+ nlen += 1 + LINK_SIZE;+ *bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS;+ *code++ = OP_KETRPOS;+ PUTINC(code, 0, nlen);+ PUT(bracode, 1, nlen);+ }++ /* For non-COND brackets, we modify the BRA code and use KETRPOS. */++ else+ {+ *bracode += 1; /* Switch to xxxPOS opcodes */+ *ketcode = OP_KETRPOS;+ }++ /* If the minimum is zero, mark it as possessive, then unset the+ possessive flag when the minimum is 0 or 1. */++ if (brazeroptr != NULL) *brazeroptr = OP_BRAPOSZERO;+ if (repeat_min < 2) possessive_quantifier = FALSE;+ }++ /* Non-possessive quantifier */++ else *ketcode = OP_KETRMAX + repeat_type;+ }+ }+ }+ break;++ /* If previous was a character type match (\d or similar), abolish it and+ create a suitable repeat item. The code is shared with single-character+ repeats by setting op_type to add a suitable offset into repeat_type.+ Note the the Unicode property types will be present only when+ SUPPORT_UNICODE is defined, but we don't wrap the little bits of code+ here because it just makes it horribly messy. */++ default:+ if (op_previous >= OP_EODN) /* Not a character type - internal error */+ {+ *errorcodeptr = ERR10;+ return 0;+ }+ else+ {+ int prop_type, prop_value;+ PCRE2_UCHAR *oldcode;++ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;++ op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */+ mclength = 0; /* Not a character */++ if (op_previous == OP_PROP || op_previous == OP_NOTPROP)+ {+ prop_type = previous[1];+ prop_value = previous[2];+ }+ else+ {+ /* Come here from just above with a character in mcbuffer/mclength. */+ OUTPUT_SINGLE_REPEAT:+ prop_type = prop_value = -1;+ }++ /* At this point, if prop_type == prop_value == -1 we either have a+ character in mcbuffer when mclength is greater than zero, or we have+ mclength zero, in which case there is a non-property character type in+ op_previous. If prop_type/value are not negative, we have a property+ character type in op_previous. */++ oldcode = code; /* Save where we were */+ code = previous; /* Usually overwrite previous item */++ /* If the maximum is zero then the minimum must also be zero; Perl allows+ this case, so we do too - by simply omitting the item altogether. */++ if (repeat_max == 0) goto END_REPEAT;++ /* Combine the op_type with the repeat_type */++ repeat_type += op_type;++ /* A minimum of zero is handled either as the special case * or ?, or as+ an UPTO, with the maximum given. */++ if (repeat_min == 0)+ {+ if (repeat_max == REPEAT_UNLIMITED) *code++ = OP_STAR + repeat_type;+ else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;+ else+ {+ *code++ = OP_UPTO + repeat_type;+ PUT2INC(code, 0, repeat_max);+ }+ }++ /* A repeat minimum of 1 is optimized into some special cases. If the+ maximum is unlimited, we use OP_PLUS. Otherwise, the original item is+ left in place and, if the maximum is greater than 1, we use OP_UPTO with+ one less than the maximum. */++ else if (repeat_min == 1)+ {+ if (repeat_max == REPEAT_UNLIMITED)+ *code++ = OP_PLUS + repeat_type;+ else+ {+ code = oldcode; /* Leave previous item in place */+ if (repeat_max == 1) goto END_REPEAT;+ *code++ = OP_UPTO + repeat_type;+ PUT2INC(code, 0, repeat_max - 1);+ }+ }++ /* The case {n,n} is just an EXACT, while the general case {n,m} is+ handled as an EXACT followed by an UPTO or STAR or QUERY. */++ else+ {+ *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */+ PUT2INC(code, 0, repeat_min);++ /* Unless repeat_max equals repeat_min, fill in the data for EXACT,+ and then generate the second opcode. For a repeated Unicode property+ match, there are two extra values that define the required property,+ and mclength is set zero to indicate this. */++ if (repeat_max != repeat_min)+ {+ if (mclength > 0)+ {+ memcpy(code, mcbuffer, CU2BYTES(mclength));+ code += mclength;+ }+ else+ {+ *code++ = op_previous;+ if (prop_type >= 0)+ {+ *code++ = prop_type;+ *code++ = prop_value;+ }+ }++ /* Now set up the following opcode */++ if (repeat_max == REPEAT_UNLIMITED)+ *code++ = OP_STAR + repeat_type;+ else+ {+ repeat_max -= repeat_min;+ if (repeat_max == 1)+ {+ *code++ = OP_QUERY + repeat_type;+ }+ else+ {+ *code++ = OP_UPTO + repeat_type;+ PUT2INC(code, 0, repeat_max);+ }+ }+ }+ }++ /* Fill in the character or character type for the final opcode. */++ if (mclength > 0)+ {+ memcpy(code, mcbuffer, CU2BYTES(mclength));+ code += mclength;+ }+ else+ {+ *code++ = op_previous;+ if (prop_type >= 0)+ {+ *code++ = prop_type;+ *code++ = prop_value;+ }+ }+ }+ break;+ } /* End of switch on different op_previous values */+++ /* If the character following a repeat is '+', possessive_quantifier is+ TRUE. For some opcodes, there are special alternative opcodes for this+ case. For anything else, we wrap the entire repeated item inside OP_ONCE+ brackets. Logically, the '+' notation is just syntactic sugar, taken from+ Sun's Java package, but the special opcodes can optimize it.++ Some (but not all) possessively repeated subpatterns have already been+ completely handled in the code just above. For them, possessive_quantifier+ is always FALSE at this stage. Note that the repeated item starts at+ tempcode, not at previous, which might be the first part of a string whose+ (former) last char we repeated. */++ if (possessive_quantifier)+ {+ int len;++ /* Possessifying an EXACT quantifier has no effect, so we can ignore it.+ However, QUERY, STAR, or UPTO may follow (for quantifiers such as {5,6},+ {5,}, or {5,10}). We skip over an EXACT item; if the length of what+ remains is greater than zero, there's a further opcode that can be+ handled. If not, do nothing, leaving the EXACT alone. */++ switch(*tempcode)+ {+ case OP_TYPEEXACT:+ tempcode += PRIV(OP_lengths)[*tempcode] ++ ((tempcode[1 + IMM2_SIZE] == OP_PROP+ || tempcode[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0);+ break;++ /* CHAR opcodes are used for exacts whose count is 1. */++ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ case OP_EXACT:+ case OP_EXACTI:+ case OP_NOTEXACT:+ case OP_NOTEXACTI:+ tempcode += PRIV(OP_lengths)[*tempcode];+#ifdef SUPPORT_UNICODE+ if (utf && HAS_EXTRALEN(tempcode[-1]))+ tempcode += GET_EXTRALEN(tempcode[-1]);+#endif+ break;++ /* For the class opcodes, the repeat operator appears at the end;+ adjust tempcode to point to it. */++ case OP_CLASS:+ case OP_NCLASS:+ tempcode += 1 + 32/sizeof(PCRE2_UCHAR);+ break;++#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+ tempcode += GET(tempcode, 1);+ break;+#endif+ }++ /* If tempcode is equal to code (which points to the end of the repeated+ item), it means we have skipped an EXACT item but there is no following+ QUERY, STAR, or UPTO; the value of len will be 0, and we do nothing. In+ all other cases, tempcode will be pointing to the repeat opcode, and will+ be less than code, so the value of len will be greater than 0. */++ len = (int)(code - tempcode);+ if (len > 0)+ {+ unsigned int repcode = *tempcode;++ /* There is a table for possessifying opcodes, all of which are less+ than OP_CALLOUT. A zero entry means there is no possessified version.+ */++ if (repcode < OP_CALLOUT && opcode_possessify[repcode] > 0)+ *tempcode = opcode_possessify[repcode];++ /* For opcode without a special possessified version, wrap the item in+ ONCE brackets. */++ else+ {+ (void)memmove(tempcode + 1 + LINK_SIZE, tempcode, CU2BYTES(len));+ code += 1 + LINK_SIZE;+ len += 1 + LINK_SIZE;+ tempcode[0] = OP_ONCE;+ *code++ = OP_KET;+ PUTINC(code, 0, len);+ PUT(tempcode, 1, len);+ }+ }+ }++ /* We set the "follows varying string" flag for subsequently encountered+ reqcus if it isn't already set and we have just passed a varying length+ item. */++ END_REPEAT:+ cb->req_varyopt |= reqvary;+ break;+++ /* ===================================================================*/+ /* Handle a 32-bit data character with a value greater than META_END. */++ case META_BIGVALUE:+ pptr++;+ goto NORMAL_CHAR;+++ /* ===============================================================*/+ /* Handle a back reference by number, which is the meta argument. The+ pattern offsets for back references to group numbers less than 10 are held+ in a special vector, to avoid using more than two parsed pattern elements+ in 64-bit environments. We only need the offset to the first occurrence,+ because if that doesn't fail, subsequent ones will also be OK. */++ case META_BACKREF:+ if (meta_arg < 10) offset = cb->small_ref_offset[meta_arg];+ else GETPLUSOFFSET(offset, pptr);++ if (meta_arg > cb->bracount)+ {+ cb->erroroffset = offset;+ *errorcodeptr = ERR15; /* Non-existent subpattern */+ return 0;+ }++ /* Come here from named backref handling when the reference is to a+ single group (that is, not to a duplicated name). The back reference+ data will have already been updated. We must disable firstcu if not+ set, to cope with cases like (?=(\w+))\1: which would otherwise set ':'+ later. */++ HANDLE_SINGLE_REFERENCE:+ if (firstcuflags == REQ_UNSET) zerofirstcuflags = firstcuflags = REQ_NONE;+ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_REFI : OP_REF;+ PUT2INC(code, 0, meta_arg);++ /* Update the map of back references, and keep the highest one. We+ could do this in parse_regex() for numerical back references, but not+ for named back references, because we don't know the numbers to which+ named back references refer. So we do it all in this function. */++ cb->backref_map |= (meta_arg < 32)? (1u << meta_arg) : 1;+ if (meta_arg > cb->top_backref) cb->top_backref = meta_arg;+ break;+++ /* ===============================================================*/+ /* Handle recursion by inserting the number of the called group (which is+ the meta argument) after OP_RECURSE. At the end of compiling the pattern is+ scanned and these numbers are replaced by offsets within the pattern. It is+ done like this to avoid problems with forward references and adjusting+ offsets when groups are duplicated and moved (as discovered in previous+ implementations). Note that a recursion does not have a set first+ character. */++ case META_RECURSE:+ GETPLUSOFFSET(offset, pptr);+ if (meta_arg > cb->bracount)+ {+ cb->erroroffset = offset;+ *errorcodeptr = ERR15; /* Non-existent subpattern */+ return 0;+ }+ HANDLE_NUMERICAL_RECURSION:+ *code = OP_RECURSE;+ PUT(code, 1, meta_arg);+ code += 1 + LINK_SIZE;+ groupsetfirstcu = FALSE;+ cb->had_recurse = TRUE;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ break;+++ /* ===============================================================*/+ /* Handle capturing parentheses; the number is the meta argument. */++ case META_CAPTURE:+ bravalue = OP_CBRA;+ skipunits = IMM2_SIZE;+ PUT2(code, 1+LINK_SIZE, meta_arg);+ cb->lastcapture = meta_arg;+ goto GROUP_PROCESS_NOTE_EMPTY;+++ /* ===============================================================*/+ /* Handle escape sequence items. For ones like \d, the ESC_values are+ arranged to be the same as the corresponding OP_values in the default case+ when PCRE2_UCP is not set (which is the only case in which they will appear+ here).++ Note: \Q and \E are never seen here, as they were dealt with in+ parse_pattern(). Neither are numerical back references or recursions, which+ were turned into META_BACKREF or META_RECURSE items, respectively. \k and+ \g, when followed by names, are turned into META_BACKREF_BYNAME or+ META_RECURSE_BYNAME. */++ case META_ESCAPE:++ /* We can test for escape sequences that consume a character because their+ values lie between ESC_b and ESC_Z; this may have to change if any new ones+ are ever created. For these sequences, we disable the setting of a first+ character if it hasn't already been set. */++ if (meta_arg > ESC_b && meta_arg < ESC_Z)+ {+ matched_char = TRUE;+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;+ }++ /* Set values to reset to if this is followed by a zero repeat. */++ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;++ /* If Unicode is not supported, \P and \p are not allowed and are+ faulted at parse time, so will never appear here. */++#ifdef SUPPORT_UNICODE+ if (meta_arg == ESC_P || meta_arg == ESC_p)+ {+ uint32_t ptype = *(++pptr) >> 16;+ uint32_t pdata = *pptr & 0xffff;++ /* The special case of \p{Any} is compiled to OP_ALLANY so as to benefit+ from the auto-anchoring code. */++ if (meta_arg == ESC_p && ptype == PT_ANY)+ {+ *code++ = OP_ALLANY;+ }+ else+ {+ *code++ = (meta_arg == ESC_p)? OP_PROP : OP_NOTPROP;+ *code++ = ptype;+ *code++ = pdata;+ }+ break; /* End META_ESCAPE */+ }+#endif++ /* For the rest (including \X when Unicode is supported - if not it's+ faulted at parse time), the OP value is the escape value when PCRE2_UCP is+ not set; if it is set, these escapes do not show up here because they are+ converted into Unicode property tests in parse_regex(). Note that \b and \B+ do a one-character lookbehind, and \A also behaves as if it does. */++ if (meta_arg == ESC_C) cb->external_flags |= PCRE2_HASBKC; /* Record */+ if ((meta_arg == ESC_b || meta_arg == ESC_B || meta_arg == ESC_A) &&+ cb->max_lookbehind == 0)+ cb->max_lookbehind = 1;++ /* In non-UTF mode, and for both 32-bit modes, we turn \C into OP_ALLANY+ instead of OP_ANYBYTE so that it works in DFA mode and in lookbehinds. */++#if PCRE2_CODE_UNIT_WIDTH == 32+ *code++ = (meta_arg == ESC_C)? OP_ALLANY : meta_arg;+#else+ *code++ = (!utf && meta_arg == ESC_C)? OP_ALLANY : meta_arg;+#endif+ break; /* End META_ESCAPE */+++ /* ===================================================================*/+ /* Handle an unrecognized meta value. A parsed pattern value less than+ META_END is a literal. Otherwise we have a problem. */++ default:+ if (meta >= META_END)+ {+#ifdef DEBUG_SHOW_PARSED+ fprintf(stderr, "** Unrecognized parsed pattern item 0x%.8x\n", *pptr);+#endif+ *errorcodeptr = ERR89; /* Internal error - unrecognized. */+ return 0;+ }++ /* Handle a literal character. We come here by goto in the case of a+ 32-bit, non-UTF character whose value is greater than META_END. */++ NORMAL_CHAR:+ meta = *pptr; /* Get the full 32 bits */+ NORMAL_CHAR_SET: /* Character is already in meta */+ matched_char = TRUE;++ /* For caseless UTF or UCP mode, check whether this character has more than+ one other case. If so, generate a special OP_PROP item instead of OP_CHARI.+ */++#ifdef SUPPORT_UNICODE+ if ((utf||ucp) && (options & PCRE2_CASELESS) != 0)+ {+ uint32_t caseset = UCD_CASESET(meta);+ if (caseset != 0)+ {+ *code++ = OP_PROP;+ *code++ = PT_CLIST;+ *code++ = caseset;+ if (firstcuflags == REQ_UNSET)+ firstcuflags = zerofirstcuflags = REQ_NONE;+ break; /* End handling this meta item */+ }+ }+#endif++ /* Caseful matches, or caseless and not one of the multicase characters. We+ come here by goto in the case of a positive class that contains only+ case-partners of a character with just two cases; matched_char has already+ been set TRUE and options fudged if necessary. */++ CLASS_CASELESS_CHAR:++ /* Get the character's code units into mcbuffer, with the length in+ mclength. When not in UTF mode, the length is always 1. */++#ifdef SUPPORT_UNICODE+ if (utf) mclength = PRIV(ord2utf)(meta, mcbuffer); else+#endif+ {+ mclength = 1;+ mcbuffer[0] = meta;+ }++ /* Generate the appropriate code */++ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_CHARI : OP_CHAR;+ memcpy(code, mcbuffer, CU2BYTES(mclength));+ code += mclength;++ /* Remember if \r or \n were seen */++ if (mcbuffer[0] == CHAR_CR || mcbuffer[0] == CHAR_NL)+ cb->external_flags |= PCRE2_HASCRORLF;++ /* Set the first and required code units appropriately. If no previous+ first code unit, set it from this character, but revert to none on a zero+ repeat. Otherwise, leave the firstcu value alone, and don't change it on+ a zero repeat. */++ if (firstcuflags == REQ_UNSET)+ {+ zerofirstcuflags = REQ_NONE;+ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;++ /* If the character is more than one code unit long, we can set a single+ firstcu only if it is not to be matched caselessly. Multiple possible+ starting code units may be picked up later in the studying code. */++ if (mclength == 1 || req_caseopt == 0)+ {+ firstcu = mcbuffer[0];+ firstcuflags = req_caseopt;+ if (mclength != 1)+ {+ reqcu = code[-1];+ reqcuflags = cb->req_varyopt;+ }+ }+ else firstcuflags = reqcuflags = REQ_NONE;+ }++ /* firstcu was previously set; we can set reqcu only if the length is+ 1 or the matching is caseful. */++ else+ {+ zerofirstcu = firstcu;+ zerofirstcuflags = firstcuflags;+ zeroreqcu = reqcu;+ zeroreqcuflags = reqcuflags;+ if (mclength == 1 || req_caseopt == 0)+ {+ reqcu = code[-1];+ reqcuflags = req_caseopt | cb->req_varyopt;+ }+ }++ /* If caselessness was temporarily instated, reset it. */++ if (reset_caseful)+ {+ options &= ~PCRE2_CASELESS;+ req_caseopt = 0;+ reset_caseful = FALSE;+ }++ break; /* End literal character handling */+ } /* End of big switch */+ } /* End of big loop */++/* Control never reaches here. */+}++++/*************************************************+* Compile regex: a sequence of alternatives *+*************************************************/++/* On entry, pptr is pointing past the bracket meta, but on return it points to+the closing bracket or META_END. The code variable is pointing at the code unit+into which the BRA operator has been stored. This function is used during the+pre-compile phase when we are trying to find out the amount of memory needed,+as well as during the real compile phase. The value of lengthptr distinguishes+the two phases.++Arguments:+ options option bits, including any changes for this subpattern+ codeptr -> the address of the current code pointer+ pptrptr -> the address of the current parsed pattern pointer+ errorcodeptr -> pointer to error code variable+ skipunits skip this many code units at start (for brackets and OP_COND)+ firstcuptr place to put the first required code unit+ firstcuflagsptr place to put the first code unit flags, or a negative number+ reqcuptr place to put the last required code unit+ reqcuflagsptr place to put the last required code unit flags, or a negative number+ bcptr pointer to the chain of currently open branches+ cb points to the data block with tables pointers etc.+ lengthptr NULL during the real compile phase+ points to length accumulator during pre-compile phase++Returns: 0 There has been an error+ +1 Success, this group must match at least one character+ -1 Success, this group may match an empty string+*/++static int+compile_regex(uint32_t options, PCRE2_UCHAR **codeptr, uint32_t **pptrptr,+ int *errorcodeptr, uint32_t skipunits, uint32_t *firstcuptr,+ int32_t *firstcuflagsptr, uint32_t *reqcuptr,int32_t *reqcuflagsptr,+ branch_chain *bcptr, compile_block *cb, PCRE2_SIZE *lengthptr)+{+PCRE2_UCHAR *code = *codeptr;+PCRE2_UCHAR *last_branch = code;+PCRE2_UCHAR *start_bracket = code;+BOOL lookbehind;+open_capitem capitem;+int capnumber = 0;+int okreturn = 1;+uint32_t *pptr = *pptrptr;+uint32_t firstcu, reqcu;+uint32_t lookbehindlength;+int32_t firstcuflags, reqcuflags;+uint32_t branchfirstcu, branchreqcu;+int32_t branchfirstcuflags, branchreqcuflags;+PCRE2_SIZE length;+branch_chain bc;++/* If set, call the external function that checks for stack availability. */++if (cb->cx->stack_guard != NULL &&+ cb->cx->stack_guard(cb->parens_depth, cb->cx->stack_guard_data))+ {+ *errorcodeptr= ERR33;+ return 0;+ }++/* Miscellaneous initialization */++bc.outer = bcptr;+bc.current_branch = code;++firstcu = reqcu = 0;+firstcuflags = reqcuflags = REQ_UNSET;++/* Accumulate the length for use in the pre-compile phase. Start with the+length of the BRA and KET and any extra code units that are required at the+beginning. We accumulate in a local variable to save frequent testing of+lengthptr for NULL. We cannot do this by looking at the value of 'code' at the+start and end of each alternative, because compiled items are discarded during+the pre-compile phase so that the workspace is not exceeded. */++length = 2 + 2*LINK_SIZE + skipunits;++/* Remember if this is a lookbehind assertion, and if it is, save its length+and skip over the pattern offset. */++lookbehind = *code == OP_ASSERTBACK ||+ *code == OP_ASSERTBACK_NOT ||+ *code == OP_ASSERTBACK_NA;++if (lookbehind)+ {+ lookbehindlength = META_DATA(pptr[-1]);+ pptr += SIZEOFFSET;+ }+else lookbehindlength = 0;++/* If this is a capturing subpattern, add to the chain of open capturing items+so that we can detect them if (*ACCEPT) is encountered. Note that only OP_CBRA+need be tested here; changing this opcode to one of its variants, e.g.+OP_SCBRAPOS, happens later, after the group has been compiled. */++if (*code == OP_CBRA)+ {+ capnumber = GET2(code, 1 + LINK_SIZE);+ capitem.number = capnumber;+ capitem.next = cb->open_caps;+ capitem.assert_depth = cb->assert_depth;+ cb->open_caps = &capitem;+ }++/* Offset is set zero to mark that this bracket is still open */++PUT(code, 1, 0);+code += 1 + LINK_SIZE + skipunits;++/* Loop for each alternative branch */++for (;;)+ {+ int branch_return;++ /* Insert OP_REVERSE if this is as lookbehind assertion. */++ if (lookbehind && lookbehindlength > 0)+ {+ *code++ = OP_REVERSE;+ PUTINC(code, 0, lookbehindlength);+ length += 1 + LINK_SIZE;+ }++ /* Now compile the branch; in the pre-compile phase its length gets added+ into the length. */++ if ((branch_return =+ compile_branch(&options, &code, &pptr, errorcodeptr, &branchfirstcu,+ &branchfirstcuflags, &branchreqcu, &branchreqcuflags, &bc,+ cb, (lengthptr == NULL)? NULL : &length)) == 0)+ return 0;++ /* If a branch can match an empty string, so can the whole group. */++ if (branch_return < 0) okreturn = -1;++ /* In the real compile phase, there is some post-processing to be done. */++ if (lengthptr == NULL)+ {+ /* If this is the first branch, the firstcu and reqcu values for the+ branch become the values for the regex. */++ if (*last_branch != OP_ALT)+ {+ firstcu = branchfirstcu;+ firstcuflags = branchfirstcuflags;+ reqcu = branchreqcu;+ reqcuflags = branchreqcuflags;+ }++ /* If this is not the first branch, the first char and reqcu have to+ match the values from all the previous branches, except that if the+ previous value for reqcu didn't have REQ_VARY set, it can still match,+ and we set REQ_VARY for the group from this branch's value. */++ else+ {+ /* If we previously had a firstcu, but it doesn't match the new branch,+ we have to abandon the firstcu for the regex, but if there was+ previously no reqcu, it takes on the value of the old firstcu. */++ if (firstcuflags != branchfirstcuflags || firstcu != branchfirstcu)+ {+ if (firstcuflags >= 0)+ {+ if (reqcuflags < 0)+ {+ reqcu = firstcu;+ reqcuflags = firstcuflags;+ }+ }+ firstcuflags = REQ_NONE;+ }++ /* If we (now or from before) have no firstcu, a firstcu from the+ branch becomes a reqcu if there isn't a branch reqcu. */++ if (firstcuflags < 0 && branchfirstcuflags >= 0 &&+ branchreqcuflags < 0)+ {+ branchreqcu = branchfirstcu;+ branchreqcuflags = branchfirstcuflags;+ }++ /* Now ensure that the reqcus match */++ if (((reqcuflags & ~REQ_VARY) != (branchreqcuflags & ~REQ_VARY)) ||+ reqcu != branchreqcu)+ reqcuflags = REQ_NONE;+ else+ {+ reqcu = branchreqcu;+ reqcuflags |= branchreqcuflags; /* To "or" REQ_VARY if present */+ }+ }+ }++ /* Handle reaching the end of the expression, either ')' or end of pattern.+ In the real compile phase, go back through the alternative branches and+ reverse the chain of offsets, with the field in the BRA item now becoming an+ offset to the first alternative. If there are no alternatives, it points to+ the end of the group. The length in the terminating ket is always the length+ of the whole bracketed item. Return leaving the pointer at the terminating+ char. */++ if (META_CODE(*pptr) != META_ALT)+ {+ if (lengthptr == NULL)+ {+ PCRE2_SIZE branch_length = code - last_branch;+ do+ {+ PCRE2_SIZE prev_length = GET(last_branch, 1);+ PUT(last_branch, 1, branch_length);+ branch_length = prev_length;+ last_branch -= branch_length;+ }+ while (branch_length > 0);+ }++ /* Fill in the ket */++ *code = OP_KET;+ PUT(code, 1, (int)(code - start_bracket));+ code += 1 + LINK_SIZE;++ /* If it was a capturing subpattern, remove the block from the chain. */++ if (capnumber > 0) cb->open_caps = cb->open_caps->next;++ /* Set values to pass back */++ *codeptr = code;+ *pptrptr = pptr;+ *firstcuptr = firstcu;+ *firstcuflagsptr = firstcuflags;+ *reqcuptr = reqcu;+ *reqcuflagsptr = reqcuflags;+ if (lengthptr != NULL)+ {+ if (OFLOW_MAX - *lengthptr < length)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ *lengthptr += length;+ }+ return okreturn;+ }++ /* Another branch follows. In the pre-compile phase, we can move the code+ pointer back to where it was for the start of the first branch. (That is,+ pretend that each branch is the only one.)++ In the real compile phase, insert an ALT node. Its length field points back+ to the previous branch while the bracket remains open. At the end the chain+ is reversed. It's done like this so that the start of the bracket has a+ zero offset until it is closed, making it possible to detect recursion. */++ if (lengthptr != NULL)+ {+ code = *codeptr + 1 + LINK_SIZE + skipunits;+ length += 1 + LINK_SIZE;+ }+ else+ {+ *code = OP_ALT;+ PUT(code, 1, (int)(code - last_branch));+ bc.current_branch = last_branch = code;+ code += 1 + LINK_SIZE;+ }++ /* Set the lookbehind length (if not in a lookbehind the value will be zero)+ and then advance past the vertical bar. */++ lookbehindlength = META_DATA(*pptr);+ pptr++;+ }+/* Control never reaches here */+}++++/*************************************************+* Check for anchored pattern *+*************************************************/++/* Try to find out if this is an anchored regular expression. Consider each+alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket+all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then+it's anchored. However, if this is a multiline pattern, then only OP_SOD will+be found, because ^ generates OP_CIRCM in that mode.++We can also consider a regex to be anchored if OP_SOM starts all its branches.+This is the code for \G, which means "match at start of match position, taking+into account the match offset".++A branch is also implicitly anchored if it starts with .* and DOTALL is set,+because that will try the rest of the pattern at all possible matching points,+so there is no point trying again.... er ....++.... except when the .* appears inside capturing parentheses, and there is a+subsequent back reference to those parentheses. We haven't enough information+to catch that case precisely.++At first, the best we could do was to detect when .* was in capturing brackets+and the highest back reference was greater than or equal to that level.+However, by keeping a bitmap of the first 31 back references, we can catch some+of the more common cases more precisely.++... A second exception is when the .* appears inside an atomic group, because+this prevents the number of characters it matches from being adjusted.++Arguments:+ code points to start of the compiled pattern+ bracket_map a bitmap of which brackets we are inside while testing; this+ handles up to substring 31; after that we just have to take+ the less precise approach+ cb points to the compile data block+ atomcount atomic group level+ inassert TRUE if in an assertion++Returns: TRUE or FALSE+*/++static BOOL+is_anchored(PCRE2_SPTR code, unsigned int bracket_map, compile_block *cb,+ int atomcount, BOOL inassert)+{+do {+ PCRE2_SPTR scode = first_significant_code(+ code + PRIV(OP_lengths)[*code], FALSE);+ int op = *scode;++ /* Non-capturing brackets */++ if (op == OP_BRA || op == OP_BRAPOS ||+ op == OP_SBRA || op == OP_SBRAPOS)+ {+ if (!is_anchored(scode, bracket_map, cb, atomcount, inassert))+ return FALSE;+ }++ /* Capturing brackets */++ else if (op == OP_CBRA || op == OP_CBRAPOS ||+ op == OP_SCBRA || op == OP_SCBRAPOS)+ {+ int n = GET2(scode, 1+LINK_SIZE);+ int new_map = bracket_map | ((n < 32)? (1u << n) : 1);+ if (!is_anchored(scode, new_map, cb, atomcount, inassert)) return FALSE;+ }++ /* Positive forward assertion */++ else if (op == OP_ASSERT || op == OP_ASSERT_NA)+ {+ if (!is_anchored(scode, bracket_map, cb, atomcount, TRUE)) return FALSE;+ }++ /* Condition. If there is no second branch, it can't be anchored. */++ else if (op == OP_COND || op == OP_SCOND)+ {+ if (scode[GET(scode,1)] != OP_ALT) return FALSE;+ if (!is_anchored(scode, bracket_map, cb, atomcount, inassert))+ return FALSE;+ }++ /* Atomic groups */++ else if (op == OP_ONCE)+ {+ if (!is_anchored(scode, bracket_map, cb, atomcount + 1, inassert))+ return FALSE;+ }++ /* .* is not anchored unless DOTALL is set (which generates OP_ALLANY) and+ it isn't in brackets that are or may be referenced or inside an atomic+ group or an assertion. Also the pattern must not contain *PRUNE or *SKIP,+ because these break the feature. Consider, for example, /(?s).*?(*PRUNE)b/+ with the subject "aab", which matches "b", i.e. not at the start of a line.+ There is also an option that disables auto-anchoring. */++ else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR ||+ op == OP_TYPEPOSSTAR))+ {+ if (scode[1] != OP_ALLANY || (bracket_map & cb->backref_map) != 0 ||+ atomcount > 0 || cb->had_pruneorskip || inassert ||+ (cb->external_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)+ return FALSE;+ }++ /* Check for explicit anchoring */++ else if (op != OP_SOD && op != OP_SOM && op != OP_CIRC) return FALSE;++ code += GET(code, 1);+ }+while (*code == OP_ALT); /* Loop for each alternative */+return TRUE;+}++++/*************************************************+* Check for starting with ^ or .* *+*************************************************/++/* This is called to find out if every branch starts with ^ or .* so that+"first char" processing can be done to speed things up in multiline+matching and for non-DOTALL patterns that start with .* (which must start at+the beginning or after \n). As in the case of is_anchored() (see above), we+have to take account of back references to capturing brackets that contain .*+because in that case we can't make the assumption. Also, the appearance of .*+inside atomic brackets or in an assertion, or in a pattern that contains *PRUNE+or *SKIP does not count, because once again the assumption no longer holds.++Arguments:+ code points to start of the compiled pattern or a group+ bracket_map a bitmap of which brackets we are inside while testing; this+ handles up to substring 31; after that we just have to take+ the less precise approach+ cb points to the compile data+ atomcount atomic group level+ inassert TRUE if in an assertion++Returns: TRUE or FALSE+*/++static BOOL+is_startline(PCRE2_SPTR code, unsigned int bracket_map, compile_block *cb,+ int atomcount, BOOL inassert)+{+do {+ PCRE2_SPTR scode = first_significant_code(+ code + PRIV(OP_lengths)[*code], FALSE);+ int op = *scode;++ /* If we are at the start of a conditional assertion group, *both* the+ conditional assertion *and* what follows the condition must satisfy the test+ for start of line. Other kinds of condition fail. Note that there may be an+ auto-callout at the start of a condition. */++ if (op == OP_COND)+ {+ scode += 1 + LINK_SIZE;++ if (*scode == OP_CALLOUT) scode += PRIV(OP_lengths)[OP_CALLOUT];+ else if (*scode == OP_CALLOUT_STR) scode += GET(scode, 1 + 2*LINK_SIZE);++ switch (*scode)+ {+ case OP_CREF:+ case OP_DNCREF:+ case OP_RREF:+ case OP_DNRREF:+ case OP_FAIL:+ case OP_FALSE:+ case OP_TRUE:+ return FALSE;++ default: /* Assertion */+ if (!is_startline(scode, bracket_map, cb, atomcount, TRUE)) return FALSE;+ do scode += GET(scode, 1); while (*scode == OP_ALT);+ scode += 1 + LINK_SIZE;+ break;+ }+ scode = first_significant_code(scode, FALSE);+ op = *scode;+ }++ /* Non-capturing brackets */++ if (op == OP_BRA || op == OP_BRAPOS ||+ op == OP_SBRA || op == OP_SBRAPOS)+ {+ if (!is_startline(scode, bracket_map, cb, atomcount, inassert))+ return FALSE;+ }++ /* Capturing brackets */++ else if (op == OP_CBRA || op == OP_CBRAPOS ||+ op == OP_SCBRA || op == OP_SCBRAPOS)+ {+ int n = GET2(scode, 1+LINK_SIZE);+ int new_map = bracket_map | ((n < 32)? (1u << n) : 1);+ if (!is_startline(scode, new_map, cb, atomcount, inassert)) return FALSE;+ }++ /* Positive forward assertions */++ else if (op == OP_ASSERT || op == OP_ASSERT_NA)+ {+ if (!is_startline(scode, bracket_map, cb, atomcount, TRUE))+ return FALSE;+ }++ /* Atomic brackets */++ else if (op == OP_ONCE)+ {+ if (!is_startline(scode, bracket_map, cb, atomcount + 1, inassert))+ return FALSE;+ }++ /* .* means "start at start or after \n" if it isn't in atomic brackets or+ brackets that may be referenced or an assertion, and as long as the pattern+ does not contain *PRUNE or *SKIP, because these break the feature. Consider,+ for example, /.*?a(*PRUNE)b/ with the subject "aab", which matches "ab",+ i.e. not at the start of a line. There is also an option that disables this+ optimization. */++ else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)+ {+ if (scode[1] != OP_ANY || (bracket_map & cb->backref_map) != 0 ||+ atomcount > 0 || cb->had_pruneorskip || inassert ||+ (cb->external_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)+ return FALSE;+ }++ /* Check for explicit circumflex; anything else gives a FALSE result. Note+ in particular that this includes atomic brackets OP_ONCE because the number+ of characters matched by .* cannot be adjusted inside them. */++ else if (op != OP_CIRC && op != OP_CIRCM) return FALSE;++ /* Move on to the next alternative */++ code += GET(code, 1);+ }+while (*code == OP_ALT); /* Loop for each alternative */+return TRUE;+}++++/*************************************************+* Scan compiled regex for recursion reference *+*************************************************/++/* This function scans through a compiled pattern until it finds an instance of+OP_RECURSE.++Arguments:+ code points to start of expression+ utf TRUE in UTF mode++Returns: pointer to the opcode for OP_RECURSE, or NULL if not found+*/++static PCRE2_SPTR+find_recurse(PCRE2_SPTR code, BOOL utf)+{+for (;;)+ {+ PCRE2_UCHAR c = *code;+ if (c == OP_END) return NULL;+ if (c == OP_RECURSE) return code;++ /* XCLASS is used for classes that cannot be represented just by a bit map.+ This includes negated single high-valued characters. CALLOUT_STR is used for+ callouts with string arguments. In both cases the length in the table is+ zero; the actual length is stored in the compiled code. */++ if (c == OP_XCLASS) code += GET(code, 1);+ else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE);++ /* Otherwise, we can get the item's length from the table, except that for+ repeated character types, we have to test for \p and \P, which have an extra+ two code units of parameters, and for MARK/PRUNE/SKIP/THEN with an argument,+ we must add in its length. */++ else+ {+ switch(c)+ {+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;+ break;++ case OP_TYPEPOSUPTO:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)+ code += 2;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ code += code[1];+ break;+ }++ /* Add in the fixed length from the table */++ code += PRIV(OP_lengths)[c];++ /* In UTF-8 and UTF-16 modes, opcodes that are followed by a character may+ be followed by a multi-unit character. The length in the table is a+ minimum, so we have to arrange to skip the extra units. */++#ifdef MAYBE_UTF_MULTI+ if (utf) switch(c)+ {+ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ case OP_EXACT:+ case OP_EXACTI:+ case OP_NOTEXACT:+ case OP_NOTEXACTI:+ case OP_UPTO:+ case OP_UPTOI:+ case OP_NOTUPTO:+ case OP_NOTUPTOI:+ case OP_MINUPTO:+ case OP_MINUPTOI:+ case OP_NOTMINUPTO:+ case OP_NOTMINUPTOI:+ case OP_POSUPTO:+ case OP_POSUPTOI:+ case OP_NOTPOSUPTO:+ case OP_NOTPOSUPTOI:+ case OP_STAR:+ case OP_STARI:+ case OP_NOTSTAR:+ case OP_NOTSTARI:+ case OP_MINSTAR:+ case OP_MINSTARI:+ case OP_NOTMINSTAR:+ case OP_NOTMINSTARI:+ case OP_POSSTAR:+ case OP_POSSTARI:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSSTARI:+ case OP_PLUS:+ case OP_PLUSI:+ case OP_NOTPLUS:+ case OP_NOTPLUSI:+ case OP_MINPLUS:+ case OP_MINPLUSI:+ case OP_NOTMINPLUS:+ case OP_NOTMINPLUSI:+ case OP_POSPLUS:+ case OP_POSPLUSI:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSPLUSI:+ case OP_QUERY:+ case OP_QUERYI:+ case OP_NOTQUERY:+ case OP_NOTQUERYI:+ case OP_MINQUERY:+ case OP_MINQUERYI:+ case OP_NOTMINQUERY:+ case OP_NOTMINQUERYI:+ case OP_POSQUERY:+ case OP_POSQUERYI:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSQUERYI:+ if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);+ break;+ }+#else+ (void)(utf); /* Keep compiler happy by referencing function argument */+#endif /* MAYBE_UTF_MULTI */+ }+ }+}++++/*************************************************+* Check for asserted fixed first code unit *+*************************************************/++/* During compilation, the "first code unit" settings from forward assertions+are discarded, because they can cause conflicts with actual literals that+follow. However, if we end up without a first code unit setting for an+unanchored pattern, it is worth scanning the regex to see if there is an+initial asserted first code unit. If all branches start with the same asserted+code unit, or with a non-conditional bracket all of whose alternatives start+with the same asserted code unit (recurse ad lib), then we return that code+unit, with the flags set to zero or REQ_CASELESS; otherwise return zero with+REQ_NONE in the flags.++Arguments:+ code points to start of compiled pattern+ flags points to the first code unit flags+ inassert non-zero if in an assertion++Returns: the fixed first code unit, or 0 with REQ_NONE in flags+*/++static uint32_t+find_firstassertedcu(PCRE2_SPTR code, int32_t *flags, uint32_t inassert)+{+uint32_t c = 0;+int cflags = REQ_NONE;++*flags = REQ_NONE;+do {+ uint32_t d;+ int dflags;+ int xl = (*code == OP_CBRA || *code == OP_SCBRA ||+ *code == OP_CBRAPOS || *code == OP_SCBRAPOS)? IMM2_SIZE:0;+ PCRE2_SPTR scode = first_significant_code(code + 1+LINK_SIZE + xl, TRUE);+ PCRE2_UCHAR op = *scode;++ switch(op)+ {+ default:+ return 0;++ case OP_BRA:+ case OP_BRAPOS:+ case OP_CBRA:+ case OP_SCBRA:+ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ case OP_ASSERT:+ case OP_ASSERT_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ d = find_firstassertedcu(scode, &dflags, inassert ++ ((op == OP_ASSERT || op == OP_ASSERT_NA)?1:0));+ if (dflags < 0)+ return 0;+ if (cflags < 0) { c = d; cflags = dflags; }+ else if (c != d || cflags != dflags) return 0;+ break;++ case OP_EXACT:+ scode += IMM2_SIZE;+ /* Fall through */++ case OP_CHAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_POSPLUS:+ if (inassert == 0) return 0;+ if (cflags < 0) { c = scode[1]; cflags = 0; }+ else if (c != scode[1]) return 0;+ break;++ case OP_EXACTI:+ scode += IMM2_SIZE;+ /* Fall through */++ case OP_CHARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_POSPLUSI:+ if (inassert == 0) return 0;++ /* If the character is more than one code unit long, we cannot set its+ first code unit when matching caselessly. Later scanning may pick up+ multiple code units. */++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (scode[1] >= 0x80) return 0;+#elif PCRE2_CODE_UNIT_WIDTH == 16+ if (scode[1] >= 0xd800 && scode[1] <= 0xdfff) return 0;+#endif+#endif++ if (cflags < 0) { c = scode[1]; cflags = REQ_CASELESS; }+ else if (c != scode[1]) return 0;+ break;+ }++ code += GET(code, 1);+ }+while (*code == OP_ALT);++*flags = cflags;+return c;+}++++/*************************************************+* Add an entry to the name/number table *+*************************************************/++/* This function is called between compiling passes to add an entry to the+name/number table, maintaining alphabetical order. Checking for permitted+and forbidden duplicates has already been done.++Arguments:+ cb the compile data block+ name the name to add+ length the length of the name+ groupno the group number+ tablecount the count of names in the table so far++Returns: nothing+*/++static void+add_name_to_table(compile_block *cb, PCRE2_SPTR name, int length,+ unsigned int groupno, uint32_t tablecount)+{+uint32_t i;+PCRE2_UCHAR *slot = cb->name_table;++for (i = 0; i < tablecount; i++)+ {+ int crc = memcmp(name, slot+IMM2_SIZE, CU2BYTES(length));+ if (crc == 0 && slot[IMM2_SIZE+length] != 0)+ crc = -1; /* Current name is a substring */++ /* Make space in the table and break the loop for an earlier name. For a+ duplicate or later name, carry on. We do this for duplicates so that in the+ simple case (when ?(| is not used) they are in order of their numbers. In all+ cases they are in the order in which they appear in the pattern. */++ if (crc < 0)+ {+ (void)memmove(slot + cb->name_entry_size, slot,+ CU2BYTES((tablecount - i) * cb->name_entry_size));+ break;+ }++ /* Continue the loop for a later or duplicate name */++ slot += cb->name_entry_size;+ }++PUT2(slot, 0, groupno);+memcpy(slot + IMM2_SIZE, name, CU2BYTES(length));++/* Add a terminating zero and fill the rest of the slot with zeroes so that+the memory is all initialized. Otherwise valgrind moans about uninitialized+memory when saving serialized compiled patterns. */++memset(slot + IMM2_SIZE + length, 0,+ CU2BYTES(cb->name_entry_size - length - IMM2_SIZE));+}++++/*************************************************+* Skip in parsed pattern *+*************************************************/++/* This function is called to skip parts of the parsed pattern when finding the+length of a lookbehind branch. It is called after (*ACCEPT) and (*FAIL) to find+the end of the branch, it is called to skip over an internal lookaround or+(DEFINE) group, and it is also called to skip to the end of a class, during+which it will never encounter nested groups (but there's no need to have+special code for that).++When called to find the end of a branch or group, pptr must point to the first+meta code inside the branch, not the branch-starting code. In other cases it+can point to the item that causes the function to be called.++Arguments:+ pptr current pointer to skip from+ skiptype PSKIP_CLASS when skipping to end of class+ PSKIP_ALT when META_ALT ends the skip+ PSKIP_KET when only META_KET ends the skip++Returns: new value of pptr+ NULL if META_END is reached - should never occur+ or for an unknown meta value - likewise+*/++static uint32_t *+parsed_skip(uint32_t *pptr, uint32_t skiptype)+{+uint32_t nestlevel = 0;++for (;; pptr++)+ {+ uint32_t meta = META_CODE(*pptr);++ switch(meta)+ {+ default: /* Just skip over most items */+ if (meta < META_END) continue; /* Literal */+ break;++ /* This should never occur. */++ case META_END:+ return NULL;++ /* The data for these items is variable in length. */++ case META_BACKREF: /* Offset is present only if group >= 10 */+ if (META_DATA(*pptr) >= 10) pptr += SIZEOFFSET;+ break;++ case META_ESCAPE: /* A few escapes are followed by data items. */+ switch (META_DATA(*pptr))+ {+ case ESC_P:+ case ESC_p:+ pptr += 1;+ break;++ case ESC_g:+ case ESC_k:+ pptr += 1 + SIZEOFFSET;+ break;+ }+ break;++ case META_MARK: /* Add the length of the name. */+ case META_COMMIT_ARG:+ case META_PRUNE_ARG:+ case META_SKIP_ARG:+ case META_THEN_ARG:+ pptr += pptr[1];+ break;++ /* These are the "active" items in this loop. */++ case META_CLASS_END:+ if (skiptype == PSKIP_CLASS) return pptr;+ break;++ case META_ATOMIC:+ case META_CAPTURE:+ case META_COND_ASSERT:+ case META_COND_DEFINE:+ case META_COND_NAME:+ case META_COND_NUMBER:+ case META_COND_RNAME:+ case META_COND_RNUMBER:+ case META_COND_VERSION:+ case META_LOOKAHEAD:+ case META_LOOKAHEADNOT:+ case META_LOOKAHEAD_NA:+ case META_LOOKBEHIND:+ case META_LOOKBEHINDNOT:+ case META_LOOKBEHIND_NA:+ case META_NOCAPTURE:+ case META_SCRIPT_RUN:+ nestlevel++;+ break;++ case META_ALT:+ if (nestlevel == 0 && skiptype == PSKIP_ALT) return pptr;+ break;++ case META_KET:+ if (nestlevel == 0) return pptr;+ nestlevel--;+ break;+ }++ /* The extra data item length for each meta is in a table. */++ meta = (meta >> 16) & 0x7fff;+ if (meta >= sizeof(meta_extra_lengths)) return NULL;+ pptr += meta_extra_lengths[meta];+ }+/* Control never reaches here */+return pptr;+}++++/*************************************************+* Find length of a parsed group *+*************************************************/++/* This is called for nested groups within a branch of a lookbehind whose+length is being computed. If all the branches in the nested group have the same+length, that is OK. On entry, the pointer must be at the first element after+the group initializing code. On exit it points to OP_KET. Caching is used to+improve processing speed when the same capturing group occurs many times.++Arguments:+ pptrptr pointer to pointer in the parsed pattern+ isinline FALSE if a reference or recursion; TRUE for inline group+ errcodeptr pointer to the errorcode+ lcptr pointer to the loop counter+ group number of captured group or -1 for a non-capturing group+ recurses chain of recurse_check to catch mutual recursion+ cb pointer to the compile data++Returns: the group length or a negative number+*/++static int+get_grouplength(uint32_t **pptrptr, BOOL isinline, int *errcodeptr, int *lcptr,+ int group, parsed_recurse_check *recurses, compile_block *cb)+{+int branchlength;+int grouplength = -1;++/* The cache can be used only if there is no possibility of there being two+groups with the same number. We do not need to set the end pointer for a group+that is being processed as a back reference or recursion, but we must do so for+an inline group. */++if (group > 0 && (cb->external_flags & PCRE2_DUPCAPUSED) == 0)+ {+ uint32_t groupinfo = cb->groupinfo[group];+ if ((groupinfo & GI_NOT_FIXED_LENGTH) != 0) return -1;+ if ((groupinfo & GI_SET_FIXED_LENGTH) != 0)+ {+ if (isinline) *pptrptr = parsed_skip(*pptrptr, PSKIP_KET);+ return groupinfo & GI_FIXED_LENGTH_MASK;+ }+ }++/* Scan the group. In this case we find the end pointer of necessity. */++for(;;)+ {+ branchlength = get_branchlength(pptrptr, errcodeptr, lcptr, recurses, cb);+ if (branchlength < 0) goto ISNOTFIXED;+ if (grouplength == -1) grouplength = branchlength;+ else if (grouplength != branchlength) goto ISNOTFIXED;+ if (**pptrptr == META_KET) break;+ *pptrptr += 1; /* Skip META_ALT */+ }++if (group > 0)+ cb->groupinfo[group] |= (uint32_t)(GI_SET_FIXED_LENGTH | grouplength);+return grouplength;++ISNOTFIXED:+if (group > 0) cb->groupinfo[group] |= GI_NOT_FIXED_LENGTH;+return -1;+}++++/*************************************************+* Find length of a parsed branch *+*************************************************/++/* Return a fixed length for a branch in a lookbehind, giving an error if the+length is not fixed. On entry, *pptrptr points to the first element inside the+branch. On exit it is set to point to the ALT or KET.++Arguments:+ pptrptr pointer to pointer in the parsed pattern+ errcodeptr pointer to error code+ lcptr pointer to loop counter+ recurses chain of recurse_check to catch mutual recursion+ cb pointer to compile block++Returns: the length, or a negative value on error+*/++static int+get_branchlength(uint32_t **pptrptr, int *errcodeptr, int *lcptr,+ parsed_recurse_check *recurses, compile_block *cb)+{+int branchlength = 0;+int grouplength;+uint32_t lastitemlength = 0;+uint32_t *pptr = *pptrptr;+PCRE2_SIZE offset;+parsed_recurse_check this_recurse;++/* A large and/or complex regex can take too long to process. This can happen+more often when (?| groups are present in the pattern because their length+cannot be cached. */++if ((*lcptr)++ > 2000)+ {+ *errcodeptr = ERR35; /* Lookbehind is too complicated */+ return -1;+ }++/* Scan the branch, accumulating the length. */++for (;; pptr++)+ {+ parsed_recurse_check *r;+ uint32_t *gptr, *gptrend;+ uint32_t escape;+ uint32_t group = 0;+ uint32_t itemlength = 0;++ if (*pptr < META_END)+ {+ itemlength = 1;+ }++ else switch (META_CODE(*pptr))+ {+ case META_KET:+ case META_ALT:+ goto EXIT;++ /* (*ACCEPT) and (*FAIL) terminate the branch, but we must skip to the+ actual termination. */++ case META_ACCEPT:+ case META_FAIL:+ pptr = parsed_skip(pptr, PSKIP_ALT);+ if (pptr == NULL) goto PARSED_SKIP_FAILED;+ goto EXIT;++ case META_MARK:+ case META_COMMIT_ARG:+ case META_PRUNE_ARG:+ case META_SKIP_ARG:+ case META_THEN_ARG:+ pptr += pptr[1] + 1;+ break;++ case META_CIRCUMFLEX:+ case META_COMMIT:+ case META_DOLLAR:+ case META_PRUNE:+ case META_SKIP:+ case META_THEN:+ break;++ case META_OPTIONS:+ pptr += 1;+ break;++ case META_BIGVALUE:+ itemlength = 1;+ pptr += 1;+ break;++ case META_CLASS:+ case META_CLASS_NOT:+ itemlength = 1;+ pptr = parsed_skip(pptr, PSKIP_CLASS);+ if (pptr == NULL) goto PARSED_SKIP_FAILED;+ break;++ case META_CLASS_EMPTY_NOT:+ case META_DOT:+ itemlength = 1;+ break;++ case META_CALLOUT_NUMBER:+ pptr += 3;+ break;++ case META_CALLOUT_STRING:+ pptr += 3 + SIZEOFFSET;+ break;++ /* Only some escapes consume a character. Of those, \R and \X are never+ allowed because they might match more than character. \C is allowed only in+ 32-bit and non-UTF 8/16-bit modes. */++ case META_ESCAPE:+ escape = META_DATA(*pptr);+ if (escape == ESC_R || escape == ESC_X) return -1;+ if (escape > ESC_b && escape < ESC_Z)+ {+#if PCRE2_CODE_UNIT_WIDTH != 32+ if ((cb->external_options & PCRE2_UTF) != 0 && escape == ESC_C)+ {+ *errcodeptr = ERR36;+ return -1;+ }+#endif+ itemlength = 1;+ if (escape == ESC_p || escape == ESC_P) pptr++; /* Skip prop data */+ }+ break;++ /* Lookaheads do not contribute to the length of this branch, but they may+ contain lookbehinds within them whose lengths need to be set. */++ case META_LOOKAHEAD:+ case META_LOOKAHEADNOT:+ case META_LOOKAHEAD_NA:+ *errcodeptr = check_lookbehinds(pptr + 1, &pptr, recurses, cb);+ if (*errcodeptr != 0) return -1;++ /* Ignore any qualifiers that follow a lookahead assertion. */++ switch (pptr[1])+ {+ case META_ASTERISK:+ case META_ASTERISK_PLUS:+ case META_ASTERISK_QUERY:+ case META_PLUS:+ case META_PLUS_PLUS:+ case META_PLUS_QUERY:+ case META_QUERY:+ case META_QUERY_PLUS:+ case META_QUERY_QUERY:+ pptr++;+ break;++ case META_MINMAX:+ case META_MINMAX_PLUS:+ case META_MINMAX_QUERY:+ pptr += 3;+ break;++ default:+ break;+ }+ break;++ /* A nested lookbehind does not contribute any length to this lookbehind,+ but must itself be checked and have its lengths set. */++ case META_LOOKBEHIND:+ case META_LOOKBEHINDNOT:+ case META_LOOKBEHIND_NA:+ if (!set_lookbehind_lengths(&pptr, errcodeptr, lcptr, recurses, cb))+ return -1;+ break;++ /* Back references and recursions are handled by very similar code. At this+ stage, the names generated in the parsing pass are available, but the main+ name table has not yet been created. So for the named varieties, scan the+ list of names in order to get the number of the first one in the pattern,+ and whether or not this name is duplicated. */++ case META_BACKREF_BYNAME:+ if ((cb->external_options & PCRE2_MATCH_UNSET_BACKREF) != 0)+ goto ISNOTFIXED;+ /* Fall through */++ case META_RECURSE_BYNAME:+ {+ int i;+ PCRE2_SPTR name;+ BOOL is_dupname = FALSE;+ named_group *ng = cb->named_groups;+ uint32_t meta_code = META_CODE(*pptr);+ uint32_t length = *(++pptr);++ GETPLUSOFFSET(offset, pptr);+ name = cb->start_pattern + offset;+ for (i = 0; i < cb->names_found; i++, ng++)+ {+ if (length == ng->length && PRIV(strncmp)(name, ng->name, length) == 0)+ {+ group = ng->number;+ is_dupname = ng->isdup;+ break;+ }+ }++ if (group == 0)+ {+ *errcodeptr = ERR15; /* Non-existent subpattern */+ cb->erroroffset = offset;+ return -1;+ }++ /* A numerical back reference can be fixed length if duplicate capturing+ groups are not being used. A non-duplicate named back reference can also+ be handled. */++ if (meta_code == META_RECURSE_BYNAME ||+ (!is_dupname && (cb->external_flags & PCRE2_DUPCAPUSED) == 0))+ goto RECURSE_OR_BACKREF_LENGTH; /* Handle as a numbered version. */+ }+ goto ISNOTFIXED; /* Duplicate name or number */++ /* The offset values for back references < 10 are in a separate vector+ because otherwise they would use more than two parsed pattern elements on+ 64-bit systems. */++ case META_BACKREF:+ if ((cb->external_options & PCRE2_MATCH_UNSET_BACKREF) != 0 ||+ (cb->external_flags & PCRE2_DUPCAPUSED) != 0)+ goto ISNOTFIXED;+ group = META_DATA(*pptr);+ if (group < 10)+ {+ offset = cb->small_ref_offset[group];+ goto RECURSE_OR_BACKREF_LENGTH;+ }++ /* Fall through */+ /* For groups >= 10 - picking up group twice does no harm. */++ /* A true recursion implies not fixed length, but a subroutine call may+ be OK. Back reference "recursions" are also failed. */++ case META_RECURSE:+ group = META_DATA(*pptr);+ GETPLUSOFFSET(offset, pptr);++ RECURSE_OR_BACKREF_LENGTH:+ if (group > cb->bracount)+ {+ cb->erroroffset = offset;+ *errcodeptr = ERR15; /* Non-existent subpattern */+ return -1;+ }+ if (group == 0) goto ISNOTFIXED; /* Local recursion */+ for (gptr = cb->parsed_pattern; *gptr != META_END; gptr++)+ {+ if (META_CODE(*gptr) == META_BIGVALUE) gptr++;+ else if (*gptr == (META_CAPTURE | group)) break;+ }++ /* We must start the search for the end of the group at the first meta code+ inside the group. Otherwise it will be treated as an enclosed group. */++ gptrend = parsed_skip(gptr + 1, PSKIP_KET);+ if (gptrend == NULL) goto PARSED_SKIP_FAILED;+ if (pptr > gptr && pptr < gptrend) goto ISNOTFIXED; /* Local recursion */+ for (r = recurses; r != NULL; r = r->prev) if (r->groupptr == gptr) break;+ if (r != NULL) goto ISNOTFIXED; /* Mutual recursion */+ this_recurse.prev = recurses;+ this_recurse.groupptr = gptr;++ /* We do not need to know the position of the end of the group, that is,+ gptr is not used after the call to get_grouplength(). Setting the second+ argument FALSE stops it scanning for the end when the length can be found+ in the cache. */++ gptr++;+ grouplength = get_grouplength(&gptr, FALSE, errcodeptr, lcptr, group,+ &this_recurse, cb);+ if (grouplength < 0)+ {+ if (*errcodeptr == 0) goto ISNOTFIXED;+ return -1; /* Error already set */+ }+ itemlength = grouplength;+ break;++ /* A (DEFINE) group is never obeyed inline and so it does not contribute to+ the length of this branch. Skip from the following item to the next+ unpaired ket. */++ case META_COND_DEFINE:+ pptr = parsed_skip(pptr + 1, PSKIP_KET);+ break;++ /* Check other nested groups - advance past the initial data for each type+ and then seek a fixed length with get_grouplength(). */++ case META_COND_NAME:+ case META_COND_NUMBER:+ case META_COND_RNAME:+ case META_COND_RNUMBER:+ pptr += 2 + SIZEOFFSET;+ goto CHECK_GROUP;++ case META_COND_ASSERT:+ pptr += 1;+ goto CHECK_GROUP;++ case META_COND_VERSION:+ pptr += 4;+ goto CHECK_GROUP;++ case META_CAPTURE:+ group = META_DATA(*pptr);+ /* Fall through */++ case META_ATOMIC:+ case META_NOCAPTURE:+ case META_SCRIPT_RUN:+ pptr++;+ CHECK_GROUP:+ grouplength = get_grouplength(&pptr, TRUE, errcodeptr, lcptr, group,+ recurses, cb);+ if (grouplength < 0) return -1;+ itemlength = grouplength;+ break;++ /* Exact repetition is OK; variable repetition is not. A repetition of zero+ must subtract the length that has already been added. */++ case META_MINMAX:+ case META_MINMAX_PLUS:+ case META_MINMAX_QUERY:+ if (pptr[1] == pptr[2])+ {+ switch(pptr[1])+ {+ case 0:+ branchlength -= lastitemlength;+ break;++ case 1:+ itemlength = 0;+ break;++ default: /* Check for integer overflow */+ if (lastitemlength != 0 && /* Should not occur, but just in case */+ INT_MAX/lastitemlength < pptr[1] - 1)+ {+ *errcodeptr = ERR87; /* Integer overflow; lookbehind too big */+ return -1;+ }+ itemlength = (pptr[1] - 1) * lastitemlength;+ break;+ }+ pptr += 2;+ break;+ }+ /* Fall through */++ /* Any other item means this branch does not have a fixed length. */++ default:+ ISNOTFIXED:+ *errcodeptr = ERR25; /* Not fixed length */+ return -1;+ }++ /* Add the item length to the branchlength, checking for integer overflow and+ for the branch length exceeding the limit. */++ if (INT_MAX - branchlength < (int)itemlength ||+ (branchlength += itemlength) > LOOKBEHIND_MAX)+ {+ *errcodeptr = ERR87;+ return -1;+ }++ /* Save this item length for use if the next item is a quantifier. */++ lastitemlength = itemlength;+ }++EXIT:+*pptrptr = pptr;+return branchlength;++PARSED_SKIP_FAILED:+*errcodeptr = ERR90;+return -1;+}++++/*************************************************+* Set lengths in a lookbehind *+*************************************************/++/* This function is called for each lookbehind, to set the lengths in its+branches. An error occurs if any branch does not have a fixed length that is+less than the maximum (65535). On exit, the pointer must be left on the final+ket.++The function also maintains the max_lookbehind value. Any lookbehind branch+that contains a nested lookbehind may actually look further back than the+length of the branch. The additional amount is passed back from+get_branchlength() as an "extra" value.++Arguments:+ pptrptr pointer to pointer in the parsed pattern+ errcodeptr pointer to error code+ lcptr pointer to loop counter+ recurses chain of recurse_check to catch mutual recursion+ cb pointer to compile block++Returns: TRUE if all is well+ FALSE otherwise, with error code and offset set+*/++static BOOL+set_lookbehind_lengths(uint32_t **pptrptr, int *errcodeptr, int *lcptr,+ parsed_recurse_check *recurses, compile_block *cb)+{+PCRE2_SIZE offset;+int branchlength;+uint32_t *bptr = *pptrptr;++READPLUSOFFSET(offset, bptr); /* Offset for error messages */+*pptrptr += SIZEOFFSET;++do+ {+ *pptrptr += 1;+ branchlength = get_branchlength(pptrptr, errcodeptr, lcptr, recurses, cb);+ if (branchlength < 0)+ {+ /* The errorcode and offset may already be set from a nested lookbehind. */+ if (*errcodeptr == 0) *errcodeptr = ERR25;+ if (cb->erroroffset == PCRE2_UNSET) cb->erroroffset = offset;+ return FALSE;+ }+ if (branchlength > cb->max_lookbehind) cb->max_lookbehind = branchlength;+ *bptr |= branchlength; /* branchlength never more than 65535 */+ bptr = *pptrptr;+ }+while (*bptr == META_ALT);++return TRUE;+}++++/*************************************************+* Check parsed pattern lookbehinds *+*************************************************/++/* This function is called at the end of parsing a pattern if any lookbehinds+were encountered. It scans the parsed pattern for them, calling+set_lookbehind_lengths() for each one. At the start, the errorcode is zero and+the error offset is marked unset. The enables the functions above not to+override settings from deeper nestings.++This function is called recursively from get_branchlength() for lookaheads in+order to process any lookbehinds that they may contain. It stops when it hits a+non-nested closing parenthesis in this case, returning a pointer to it.++Arguments+ pptr points to where to start (start of pattern or start of lookahead)+ retptr if not NULL, return the ket pointer here+ recurses chain of recurse_check to catch mutual recursion+ cb points to the compile block++Returns: 0 on success, or an errorcode (cb->erroroffset will be set)+*/++static int+check_lookbehinds(uint32_t *pptr, uint32_t **retptr,+ parsed_recurse_check *recurses, compile_block *cb)+{+int errorcode = 0;+int loopcount = 0;+int nestlevel = 0;++cb->erroroffset = PCRE2_UNSET;++for (; *pptr != META_END; pptr++)+ {+ if (*pptr < META_END) continue; /* Literal */++ switch (META_CODE(*pptr))+ {+ default:+ return ERR70; /* Unrecognized meta code */++ case META_ESCAPE:+ if (*pptr - META_ESCAPE == ESC_P || *pptr - META_ESCAPE == ESC_p)+ pptr += 1;+ break;++ case META_KET:+ if (--nestlevel < 0)+ {+ if (retptr != NULL) *retptr = pptr;+ return 0;+ }+ break;++ case META_ATOMIC:+ case META_CAPTURE:+ case META_COND_ASSERT:+ case META_LOOKAHEAD:+ case META_LOOKAHEADNOT:+ case META_LOOKAHEAD_NA:+ case META_NOCAPTURE:+ case META_SCRIPT_RUN:+ nestlevel++;+ break;++ case META_ACCEPT:+ case META_ALT:+ case META_ASTERISK:+ case META_ASTERISK_PLUS:+ case META_ASTERISK_QUERY:+ case META_BACKREF:+ case META_CIRCUMFLEX:+ case META_CLASS:+ case META_CLASS_EMPTY:+ case META_CLASS_EMPTY_NOT:+ case META_CLASS_END:+ case META_CLASS_NOT:+ case META_COMMIT:+ case META_DOLLAR:+ case META_DOT:+ case META_FAIL:+ case META_PLUS:+ case META_PLUS_PLUS:+ case META_PLUS_QUERY:+ case META_PRUNE:+ case META_QUERY:+ case META_QUERY_PLUS:+ case META_QUERY_QUERY:+ case META_RANGE_ESCAPED:+ case META_RANGE_LITERAL:+ case META_SKIP:+ case META_THEN:+ break;++ case META_RECURSE:+ pptr += SIZEOFFSET;+ break;++ case META_BACKREF_BYNAME:+ case META_RECURSE_BYNAME:+ pptr += 1 + SIZEOFFSET;+ break;++ case META_COND_DEFINE:+ pptr += SIZEOFFSET;+ nestlevel++;+ break;++ case META_COND_NAME:+ case META_COND_NUMBER:+ case META_COND_RNAME:+ case META_COND_RNUMBER:+ pptr += 1 + SIZEOFFSET;+ nestlevel++;+ break;++ case META_COND_VERSION:+ pptr += 3;+ nestlevel++;+ break;++ case META_CALLOUT_STRING:+ pptr += 3 + SIZEOFFSET;+ break;++ case META_BIGVALUE:+ case META_OPTIONS:+ case META_POSIX:+ case META_POSIX_NEG:+ pptr += 1;+ break;++ case META_MINMAX:+ case META_MINMAX_QUERY:+ case META_MINMAX_PLUS:+ pptr += 2;+ break;++ case META_CALLOUT_NUMBER:+ pptr += 3;+ break;++ case META_MARK:+ case META_COMMIT_ARG:+ case META_PRUNE_ARG:+ case META_SKIP_ARG:+ case META_THEN_ARG:+ pptr += 1 + pptr[1];+ break;++ case META_LOOKBEHIND:+ case META_LOOKBEHINDNOT:+ case META_LOOKBEHIND_NA:+ if (!set_lookbehind_lengths(&pptr, &errorcode, &loopcount, recurses, cb))+ return errorcode;+ break;+ }+ }++return 0;+}++++/*************************************************+* External function to compile a pattern *+*************************************************/++/* This function reads a regular expression in the form of a string and returns+a pointer to a block of store holding a compiled version of the expression.++Arguments:+ pattern the regular expression+ patlen the length of the pattern, or PCRE2_ZERO_TERMINATED+ options option bits+ errorptr pointer to errorcode+ erroroffset pointer to error offset+ ccontext points to a compile context or is NULL++Returns: pointer to compiled data block, or NULL on error,+ with errorcode and erroroffset set+*/++PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION+pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE patlen, uint32_t options,+ int *errorptr, PCRE2_SIZE *erroroffset, pcre2_compile_context *ccontext)+{+BOOL utf; /* Set TRUE for UTF mode */+BOOL ucp; /* Set TRUE for UCP mode */+BOOL has_lookbehind = FALSE; /* Set TRUE if a lookbehind is found */+BOOL zero_terminated; /* Set TRUE for zero-terminated pattern */+pcre2_real_code *re = NULL; /* What we will return */+compile_block cb; /* "Static" compile-time data */+const uint8_t *tables; /* Char tables base pointer */++PCRE2_UCHAR *code; /* Current pointer in compiled code */+PCRE2_SPTR codestart; /* Start of compiled code */+PCRE2_SPTR ptr; /* Current pointer in pattern */+uint32_t *pptr; /* Current pointer in parsed pattern */++PCRE2_SIZE length = 1; /* Allow for final END opcode */+PCRE2_SIZE usedlength; /* Actual length used */+PCRE2_SIZE re_blocksize; /* Size of memory block */+PCRE2_SIZE big32count = 0; /* 32-bit literals >= 0x80000000 */+PCRE2_SIZE parsed_size_needed; /* Needed for parsed pattern */++int32_t firstcuflags, reqcuflags; /* Type of first/req code unit */+uint32_t firstcu, reqcu; /* Value of first/req code unit */+uint32_t setflags = 0; /* NL and BSR set flags */++uint32_t skipatstart; /* When checking (*UTF) etc */+uint32_t limit_heap = UINT32_MAX;+uint32_t limit_match = UINT32_MAX; /* Unset match limits */+uint32_t limit_depth = UINT32_MAX;++int newline = 0; /* Unset; can be set by the pattern */+int bsr = 0; /* Unset; can be set by the pattern */+int errorcode = 0; /* Initialize to avoid compiler warn */+int regexrc; /* Return from compile */++uint32_t i; /* Local loop counter */++/* Comments at the head of this file explain about these variables. */++uint32_t stack_groupinfo[GROUPINFO_DEFAULT_SIZE];+uint32_t stack_parsed_pattern[PARSED_PATTERN_DEFAULT_SIZE];+named_group named_groups[NAMED_GROUP_LIST_SIZE];++/* The workspace is used in different ways in the different compiling phases.+It needs to be 16-bit aligned for the preliminary parsing scan. */++uint32_t c16workspace[C16_WORK_SIZE];+PCRE2_UCHAR *cworkspace = (PCRE2_UCHAR *)c16workspace;+++/* -------------- Check arguments and set up the pattern ----------------- */++/* There must be error code and offset pointers. */++if (errorptr == NULL || erroroffset == NULL) return NULL;+*errorptr = ERR0;+*erroroffset = 0;++/* There must be a pattern! */++if (pattern == NULL)+ {+ *errorptr = ERR16;+ return NULL;+ }++/* A NULL compile context means "use a default context" */++if (ccontext == NULL)+ ccontext = (pcre2_compile_context *)(&PRIV(default_compile_context));++/* PCRE2_MATCH_INVALID_UTF implies UTF */++if ((options & PCRE2_MATCH_INVALID_UTF) != 0) options |= PCRE2_UTF;++/* Check that all undefined public option bits are zero. */++if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0 ||+ (ccontext->extra_options & ~PUBLIC_COMPILE_EXTRA_OPTIONS) != 0)+ {+ *errorptr = ERR17;+ return NULL;+ }++if ((options & PCRE2_LITERAL) != 0 &&+ ((options & ~PUBLIC_LITERAL_COMPILE_OPTIONS) != 0 ||+ (ccontext->extra_options & ~PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS) != 0))+ {+ *errorptr = ERR92;+ return NULL;+ }++/* A zero-terminated pattern is indicated by the special length value+PCRE2_ZERO_TERMINATED. Check for an overlong pattern. */++if ((zero_terminated = (patlen == PCRE2_ZERO_TERMINATED)))+ patlen = PRIV(strlen)(pattern);++if (patlen > ccontext->max_pattern_length)+ {+ *errorptr = ERR88;+ return NULL;+ }++/* From here on, all returns from this function should end up going via the+EXIT label. */+++/* ------------ Initialize the "static" compile data -------------- */++tables = (ccontext->tables != NULL)? ccontext->tables : PRIV(default_tables);++cb.lcc = tables + lcc_offset; /* Individual */+cb.fcc = tables + fcc_offset; /* character */+cb.cbits = tables + cbits_offset; /* tables */+cb.ctypes = tables + ctypes_offset;++cb.assert_depth = 0;+cb.bracount = 0;+cb.cx = ccontext;+cb.dupnames = FALSE;+cb.end_pattern = pattern + patlen;+cb.erroroffset = 0;+cb.external_flags = 0;+cb.external_options = options;+cb.groupinfo = stack_groupinfo;+cb.had_recurse = FALSE;+cb.lastcapture = 0;+cb.max_lookbehind = 0;+cb.name_entry_size = 0;+cb.name_table = NULL;+cb.named_groups = named_groups;+cb.named_group_list_size = NAMED_GROUP_LIST_SIZE;+cb.names_found = 0;+cb.open_caps = NULL;+cb.parens_depth = 0;+cb.parsed_pattern = stack_parsed_pattern;+cb.req_varyopt = 0;+cb.start_code = cworkspace;+cb.start_pattern = pattern;+cb.start_workspace = cworkspace;+cb.workspace_size = COMPILE_WORK_SIZE;++/* Maximum back reference and backref bitmap. The bitmap records up to 31 back+references to help in deciding whether (.*) can be treated as anchored or not.+*/++cb.top_backref = 0;+cb.backref_map = 0;++/* Escape sequences \1 to \9 are always back references, but as they are only+two characters long, only two elements can be used in the parsed_pattern+vector. The first contains the reference, and we'd like to use the second to+record the offset in the pattern, so that forward references to non-existent+groups can be diagnosed later with an offset. However, on 64-bit systems,+PCRE2_SIZE won't fit. Instead, we have a vector of offsets for the first+occurrence of \1 to \9, indexed by the second parsed_pattern value. All other+references have enough space for the offset to be put into the parsed pattern.+*/++for (i = 0; i < 10; i++) cb.small_ref_offset[i] = PCRE2_UNSET;+++/* --------------- Start looking at the pattern --------------- */++/* Unless PCRE2_LITERAL is set, check for global one-time option settings at+the start of the pattern, and remember the offset to the actual regex. With+valgrind support, make the terminator of a zero-terminated pattern+inaccessible. This catches bugs that would otherwise only show up for+non-zero-terminated patterns. */++#ifdef SUPPORT_VALGRIND+if (zero_terminated) VALGRIND_MAKE_MEM_NOACCESS(pattern + patlen, CU2BYTES(1));+#endif++ptr = pattern;+skipatstart = 0;++if ((options & PCRE2_LITERAL) == 0)+ {+ while (patlen - skipatstart >= 2 &&+ ptr[skipatstart] == CHAR_LEFT_PARENTHESIS &&+ ptr[skipatstart+1] == CHAR_ASTERISK)+ {+ for (i = 0; i < sizeof(pso_list)/sizeof(pso); i++)+ {+ uint32_t c, pp;+ pso *p = pso_list + i;++ if (patlen - skipatstart - 2 >= p->length &&+ PRIV(strncmp_c8)(ptr + skipatstart + 2, (char *)(p->name),+ p->length) == 0)+ {+ skipatstart += p->length + 2;+ switch(p->type)+ {+ case PSO_OPT:+ cb.external_options |= p->value;+ break;++ case PSO_FLG:+ setflags |= p->value;+ break;++ case PSO_NL:+ newline = p->value;+ setflags |= PCRE2_NL_SET;+ break;++ case PSO_BSR:+ bsr = p->value;+ setflags |= PCRE2_BSR_SET;+ break;++ case PSO_LIMM:+ case PSO_LIMD:+ case PSO_LIMH:+ c = 0;+ pp = skipatstart;+ if (!IS_DIGIT(ptr[pp]))+ {+ errorcode = ERR60;+ ptr += pp;+ goto HAD_EARLY_ERROR;+ }+ while (IS_DIGIT(ptr[pp]))+ {+ if (c > UINT32_MAX / 10 - 1) break; /* Integer overflow */+ c = c*10 + (ptr[pp++] - CHAR_0);+ }+ if (ptr[pp++] != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR60;+ ptr += pp;+ goto HAD_EARLY_ERROR;+ }+ if (p->type == PSO_LIMH) limit_heap = c;+ else if (p->type == PSO_LIMM) limit_match = c;+ else limit_depth = c;+ skipatstart += pp - skipatstart;+ break;+ }+ break; /* Out of the table scan loop */+ }+ }+ if (i >= sizeof(pso_list)/sizeof(pso)) break; /* Out of pso loop */+ }+ }++/* End of pattern-start options; advance to start of real regex. */++ptr += skipatstart;++/* Can't support UTF or UCP if PCRE2 was built without Unicode support. */++#ifndef SUPPORT_UNICODE+if ((cb.external_options & (PCRE2_UTF|PCRE2_UCP)) != 0)+ {+ errorcode = ERR32;+ goto HAD_EARLY_ERROR;+ }+#endif++/* Check UTF. We have the original options in 'options', with that value as+modified by (*UTF) etc in cb->external_options. The extra option+PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not permitted in UTF-16 mode because the+surrogate code points cannot be represented in UTF-16. */++utf = (cb.external_options & PCRE2_UTF) != 0;+if (utf)+ {+ if ((options & PCRE2_NEVER_UTF) != 0)+ {+ errorcode = ERR74;+ goto HAD_EARLY_ERROR;+ }+ if ((options & PCRE2_NO_UTF_CHECK) == 0 &&+ (errorcode = PRIV(valid_utf)(pattern, patlen, erroroffset)) != 0)+ goto HAD_ERROR; /* Offset was set by valid_utf() */++#if PCRE2_CODE_UNIT_WIDTH == 16+ if ((ccontext->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) != 0)+ {+ errorcode = ERR91;+ goto HAD_EARLY_ERROR;+ }+#endif+ }++/* Check UCP lockout. */++ucp = (cb.external_options & PCRE2_UCP) != 0;+if (ucp && (cb.external_options & PCRE2_NEVER_UCP) != 0)+ {+ errorcode = ERR75;+ goto HAD_EARLY_ERROR;+ }++/* Process the BSR setting. */++if (bsr == 0) bsr = ccontext->bsr_convention;++/* Process the newline setting. */++if (newline == 0) newline = ccontext->newline_convention;+cb.nltype = NLTYPE_FIXED;+switch(newline)+ {+ case PCRE2_NEWLINE_CR:+ cb.nllen = 1;+ cb.nl[0] = CHAR_CR;+ break;++ case PCRE2_NEWLINE_LF:+ cb.nllen = 1;+ cb.nl[0] = CHAR_NL;+ break;++ case PCRE2_NEWLINE_NUL:+ cb.nllen = 1;+ cb.nl[0] = CHAR_NUL;+ break;++ case PCRE2_NEWLINE_CRLF:+ cb.nllen = 2;+ cb.nl[0] = CHAR_CR;+ cb.nl[1] = CHAR_NL;+ break;++ case PCRE2_NEWLINE_ANY:+ cb.nltype = NLTYPE_ANY;+ break;++ case PCRE2_NEWLINE_ANYCRLF:+ cb.nltype = NLTYPE_ANYCRLF;+ break;++ default:+ errorcode = ERR56;+ goto HAD_EARLY_ERROR;+ }++/* Pre-scan the pattern to do two things: (1) Discover the named groups and+their numerical equivalents, so that this information is always available for+the remaining processing. (2) At the same time, parse the pattern and put a+processed version into the parsed_pattern vector. This has escapes interpreted+and comments removed (amongst other things).++In all but one case, when PCRE2_AUTO_CALLOUT is not set, the number of unsigned+32-bit ints in the parsed pattern is bounded by the length of the pattern plus+one (for the terminator) plus four if PCRE2_EXTRA_WORD or PCRE2_EXTRA_LINE is+set. The exceptional case is when running in 32-bit, non-UTF mode, when literal+characters greater than META_END (0x80000000) have to be coded as two units. In+this case, therefore, we scan the pattern to check for such values. */++#if PCRE2_CODE_UNIT_WIDTH == 32+if (!utf)+ {+ PCRE2_SPTR p;+ for (p = ptr; p < cb.end_pattern; p++) if (*p >= META_END) big32count++;+ }+#endif++/* Ensure that the parsed pattern buffer is big enough. When PCRE2_AUTO_CALLOUT+is set we have to assume a numerical callout (4 elements) for each character+plus one at the end. This is overkill, but memory is plentiful these days. For+many smaller patterns the vector on the stack (which was set up above) can be+used. */++parsed_size_needed = patlen - skipatstart + big32count;++if ((ccontext->extra_options &+ (PCRE2_EXTRA_MATCH_WORD|PCRE2_EXTRA_MATCH_LINE)) != 0)+ parsed_size_needed += 4;++if ((options & PCRE2_AUTO_CALLOUT) != 0)+ parsed_size_needed = (parsed_size_needed + 1) * 5;++if (parsed_size_needed >= PARSED_PATTERN_DEFAULT_SIZE)+ {+ uint32_t *heap_parsed_pattern = ccontext->memctl.malloc(+ (parsed_size_needed + 1) * sizeof(uint32_t), ccontext->memctl.memory_data);+ if (heap_parsed_pattern == NULL)+ {+ *errorptr = ERR21;+ goto EXIT;+ }+ cb.parsed_pattern = heap_parsed_pattern;+ }+cb.parsed_pattern_end = cb.parsed_pattern + parsed_size_needed + 1;++/* Do the parsing scan. */++errorcode = parse_regex(ptr, cb.external_options, &has_lookbehind, &cb);+if (errorcode != 0) goto HAD_CB_ERROR;++/* Workspace is needed to remember information about numbered groups: whether a+group can match an empty string and what its fixed length is. This is done to+avoid the possibility of recursive references causing very long compile times+when checking these features. Unnumbered groups do not have this exposure since+they cannot be referenced. We use an indexed vector for this purpose. If there+are sufficiently few groups, the default vector on the stack, as set up above,+can be used. Otherwise we have to get/free a special vector. The vector must be+initialized to zero. */++if (cb.bracount >= GROUPINFO_DEFAULT_SIZE)+ {+ cb.groupinfo = ccontext->memctl.malloc(+ (cb.bracount + 1)*sizeof(uint32_t), ccontext->memctl.memory_data);+ if (cb.groupinfo == NULL)+ {+ errorcode = ERR21;+ cb.erroroffset = 0;+ goto HAD_CB_ERROR;+ }+ }+memset(cb.groupinfo, 0, (cb.bracount + 1) * sizeof(uint32_t));++/* If there were any lookbehinds, scan the parsed pattern to figure out their+lengths. */++if (has_lookbehind)+ {+ errorcode = check_lookbehinds(cb.parsed_pattern, NULL, NULL, &cb);+ if (errorcode != 0) goto HAD_CB_ERROR;+ }++/* For debugging, there is a function that shows the parsed data vector. */++#ifdef DEBUG_SHOW_PARSED+fprintf(stderr, "+++ Pre-scan complete:\n");+show_parsed(&cb);+#endif++/* For debugging capturing information this code can be enabled. */++#ifdef DEBUG_SHOW_CAPTURES+ {+ named_group *ng = cb.named_groups;+ fprintf(stderr, "+++Captures: %d\n", cb.bracount);+ for (i = 0; i < cb.names_found; i++, ng++)+ {+ fprintf(stderr, "+++%3d %.*s\n", ng->number, ng->length, ng->name);+ }+ }+#endif++/* Pretend to compile the pattern while actually just accumulating the amount+of memory required in the 'length' variable. This behaviour is triggered by+passing a non-NULL final argument to compile_regex(). We pass a block of+workspace (cworkspace) for it to compile parts of the pattern into; the+compiled code is discarded when it is no longer needed, so hopefully this+workspace will never overflow, though there is a test for its doing so.++On error, errorcode will be set non-zero, so we don't need to look at the+result of the function. The initial options have been put into the cb block,+but we still have to pass a separate options variable (the first argument)+because the options may change as the pattern is processed. */++cb.erroroffset = patlen; /* For any subsequent errors that do not set it */+pptr = cb.parsed_pattern;+code = cworkspace;+*code = OP_BRA;++(void)compile_regex(cb.external_options, &code, &pptr, &errorcode, 0, &firstcu,+ &firstcuflags, &reqcu, &reqcuflags, NULL, &cb, &length);++if (errorcode != 0) goto HAD_CB_ERROR; /* Offset is in cb.erroroffset */++/* This should be caught in compile_regex(), but just in case... */++if (length > MAX_PATTERN_SIZE)+ {+ errorcode = ERR20;+ goto HAD_CB_ERROR;+ }++/* Compute the size of, and then get and initialize, the data block for storing+the compiled pattern and names table. Integer overflow should no longer be+possible because nowadays we limit the maximum value of cb.names_found and+cb.name_entry_size. */++re_blocksize = sizeof(pcre2_real_code) ++ CU2BYTES(length ++ (PCRE2_SIZE)cb.names_found * (PCRE2_SIZE)cb.name_entry_size);+re = (pcre2_real_code *)+ ccontext->memctl.malloc(re_blocksize, ccontext->memctl.memory_data);+if (re == NULL)+ {+ errorcode = ERR21;+ goto HAD_CB_ERROR;+ }++/* The compiler may put padding at the end of the pcre2_real_code structure in+order to round it up to a multiple of 4 or 8 bytes. This means that when a+compiled pattern is copied (for example, when serialized) undefined bytes are+read, and this annoys debuggers such as valgrind. To avoid this, we explicitly+write to the last 8 bytes of the structure before setting the fields. */++memset((char *)re + sizeof(pcre2_real_code) - 8, 0, 8);+re->memctl = ccontext->memctl;+re->tables = tables;+re->executable_jit = NULL;+memset(re->start_bitmap, 0, 32 * sizeof(uint8_t));+re->blocksize = re_blocksize;+re->magic_number = MAGIC_NUMBER;+re->compile_options = options;+re->overall_options = cb.external_options;+re->extra_options = ccontext->extra_options;+re->flags = PCRE2_CODE_UNIT_WIDTH/8 | cb.external_flags | setflags;+re->limit_heap = limit_heap;+re->limit_match = limit_match;+re->limit_depth = limit_depth;+re->first_codeunit = 0;+re->last_codeunit = 0;+re->bsr_convention = bsr;+re->newline_convention = newline;+re->max_lookbehind = 0;+re->minlength = 0;+re->top_bracket = 0;+re->top_backref = 0;+re->name_entry_size = cb.name_entry_size;+re->name_count = cb.names_found;++/* The basic block is immediately followed by the name table, and the compiled+code follows after that. */++codestart = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code)) ++ re->name_entry_size * re->name_count;++/* Update the compile data block for the actual compile. The starting points of+the name/number translation table and of the code are passed around in the+compile data block. The start/end pattern and initial options are already set+from the pre-compile phase, as is the name_entry_size field. */++cb.parens_depth = 0;+cb.assert_depth = 0;+cb.lastcapture = 0;+cb.name_table = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code));+cb.start_code = codestart;+cb.req_varyopt = 0;+cb.had_accept = FALSE;+cb.had_pruneorskip = FALSE;+cb.open_caps = NULL;++/* If any named groups were found, create the name/number table from the list+created in the pre-pass. */++if (cb.names_found > 0)+ {+ named_group *ng = cb.named_groups;+ for (i = 0; i < cb.names_found; i++, ng++)+ add_name_to_table(&cb, ng->name, ng->length, ng->number, i);+ }++/* Set up a starting, non-extracting bracket, then compile the expression. On+error, errorcode will be set non-zero, so we don't need to look at the result+of the function here. */++pptr = cb.parsed_pattern;+code = (PCRE2_UCHAR *)codestart;+*code = OP_BRA;+regexrc = compile_regex(re->overall_options, &code, &pptr, &errorcode, 0,+ &firstcu, &firstcuflags, &reqcu, &reqcuflags, NULL, &cb, NULL);+if (regexrc < 0) re->flags |= PCRE2_MATCH_EMPTY;+re->top_bracket = cb.bracount;+re->top_backref = cb.top_backref;+re->max_lookbehind = cb.max_lookbehind;++if (cb.had_accept)+ {+ reqcu = 0; /* Must disable after (*ACCEPT) */+ reqcuflags = REQ_NONE;+ re->flags |= PCRE2_HASACCEPT; /* Disables minimum length */+ }++/* Fill in the final opcode and check for disastrous overflow. If no overflow,+but the estimated length exceeds the really used length, adjust the value of+re->blocksize, and if valgrind support is configured, mark the extra allocated+memory as unaddressable, so that any out-of-bound reads can be detected. */++*code++ = OP_END;+usedlength = code - codestart;+if (usedlength > length) errorcode = ERR23; else+ {+ re->blocksize -= CU2BYTES(length - usedlength);+#ifdef SUPPORT_VALGRIND+ VALGRIND_MAKE_MEM_NOACCESS(code, CU2BYTES(length - usedlength));+#endif+ }++/* Scan the pattern for recursion/subroutine calls and convert the group+numbers into offsets. Maintain a small cache so that repeated groups containing+recursions are efficiently handled. */++#define RSCAN_CACHE_SIZE 8++if (errorcode == 0 && cb.had_recurse)+ {+ PCRE2_UCHAR *rcode;+ PCRE2_SPTR rgroup;+ unsigned int ccount = 0;+ int start = RSCAN_CACHE_SIZE;+ recurse_cache rc[RSCAN_CACHE_SIZE];++ for (rcode = (PCRE2_UCHAR *)find_recurse(codestart, utf);+ rcode != NULL;+ rcode = (PCRE2_UCHAR *)find_recurse(rcode + 1 + LINK_SIZE, utf))+ {+ int p, groupnumber;++ groupnumber = (int)GET(rcode, 1);+ if (groupnumber == 0) rgroup = codestart; else+ {+ PCRE2_SPTR search_from = codestart;+ rgroup = NULL;+ for (i = 0, p = start; i < ccount; i++, p = (p + 1) & 7)+ {+ if (groupnumber == rc[p].groupnumber)+ {+ rgroup = rc[p].group;+ break;+ }++ /* Group n+1 must always start to the right of group n, so we can save+ search time below when the new group number is greater than any of the+ previously found groups. */++ if (groupnumber > rc[p].groupnumber) search_from = rc[p].group;+ }++ if (rgroup == NULL)+ {+ rgroup = PRIV(find_bracket)(search_from, utf, groupnumber);+ if (rgroup == NULL)+ {+ errorcode = ERR53;+ break;+ }+ if (--start < 0) start = RSCAN_CACHE_SIZE - 1;+ rc[start].groupnumber = groupnumber;+ rc[start].group = rgroup;+ if (ccount < RSCAN_CACHE_SIZE) ccount++;+ }+ }++ PUT(rcode, 1, rgroup - codestart);+ }+ }++/* In rare debugging situations we sometimes need to look at the compiled code+at this stage. */++#ifdef DEBUG_CALL_PRINTINT+pcre2_printint(re, stderr, TRUE);+fprintf(stderr, "Length=%lu Used=%lu\n", length, usedlength);+#endif++/* Unless disabled, check whether any single character iterators can be+auto-possessified. The function overwrites the appropriate opcode values, so+the type of the pointer must be cast. NOTE: the intermediate variable "temp" is+used in this code because at least one compiler gives a warning about loss of+"const" attribute if the cast (PCRE2_UCHAR *)codestart is used directly in the+function call. */++if (errorcode == 0 && (re->overall_options & PCRE2_NO_AUTO_POSSESS) == 0)+ {+ PCRE2_UCHAR *temp = (PCRE2_UCHAR *)codestart;+ if (PRIV(auto_possessify)(temp, &cb) != 0) errorcode = ERR80;+ }++/* Failed to compile, or error while post-processing. */++if (errorcode != 0) goto HAD_CB_ERROR;++/* Successful compile. If the anchored option was not passed, set it if+we can determine that the pattern is anchored by virtue of ^ characters or \A+or anything else, such as starting with non-atomic .* when DOTALL is set and+there are no occurrences of *PRUNE or *SKIP (though there is an option to+disable this case). */++if ((re->overall_options & PCRE2_ANCHORED) == 0 &&+ is_anchored(codestart, 0, &cb, 0, FALSE))+ re->overall_options |= PCRE2_ANCHORED;++/* Set up the first code unit or startline flag, the required code unit, and+then study the pattern. This code need not be obeyed if PCRE2_NO_START_OPTIMIZE+is set, as the data it would create will not be used. Note that a first code+unit (but not the startline flag) is useful for anchored patterns because it+can still give a quick "no match" and also avoid searching for a last code+unit. */++if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)+ {+ int minminlength = 0; /* For minimal minlength from first/required CU */++ /* If we do not have a first code unit, see if there is one that is asserted+ (these are not saved during the compile because they can cause conflicts with+ actual literals that follow). */++ if (firstcuflags < 0)+ firstcu = find_firstassertedcu(codestart, &firstcuflags, 0);++ /* Save the data for a first code unit. The existence of one means the+ minimum length must be at least 1. */++ if (firstcuflags >= 0)+ {+ re->first_codeunit = firstcu;+ re->flags |= PCRE2_FIRSTSET;+ minminlength++;++ /* Handle caseless first code units. */++ if ((firstcuflags & REQ_CASELESS) != 0)+ {+ if (firstcu < 128 || (!utf && !ucp && firstcu < 255))+ {+ if (cb.fcc[firstcu] != firstcu) re->flags |= PCRE2_FIRSTCASELESS;+ }++ /* The first code unit is > 128 in UTF or UCP mode, or > 255 otherwise.+ In 8-bit UTF mode, codepoints in the range 128-255 are introductory code+ points and cannot have another case, but if UCP is set they may do. */++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+ else if (ucp && !utf && UCD_OTHERCASE(firstcu) != firstcu)+ re->flags |= PCRE2_FIRSTCASELESS;+#else+ else if ((utf || ucp) && firstcu <= MAX_UTF_CODE_POINT &&+ UCD_OTHERCASE(firstcu) != firstcu)+ re->flags |= PCRE2_FIRSTCASELESS;+#endif+#endif /* SUPPORT_UNICODE */+ }+ }++ /* When there is no first code unit, for non-anchored patterns, see if we can+ set the PCRE2_STARTLINE flag. This is helpful for multiline matches when all+ branches start with ^ and also when all branches start with non-atomic .* for+ non-DOTALL matches when *PRUNE and SKIP are not present. (There is an option+ that disables this case.) */++ else if ((re->overall_options & PCRE2_ANCHORED) == 0 &&+ is_startline(codestart, 0, &cb, 0, FALSE))+ re->flags |= PCRE2_STARTLINE;++ /* Handle the "required code unit", if one is set. In the UTF case we can+ increment the minimum minimum length only if we are sure this really is a+ different character and not a non-starting code unit of the first character,+ because the minimum length count is in characters, not code units. */++ if (reqcuflags >= 0)+ {+#if PCRE2_CODE_UNIT_WIDTH == 16+ if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */+ firstcuflags < 0 || /* First not set */+ (firstcu & 0xf800) != 0xd800 || /* First not surrogate */+ (reqcu & 0xfc00) != 0xdc00) /* Req not low surrogate */+#elif PCRE2_CODE_UNIT_WIDTH == 8+ if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */+ firstcuflags < 0 || /* First not set */+ (firstcu & 0x80) == 0 || /* First is ASCII */+ (reqcu & 0x80) == 0) /* Req is ASCII */+#endif+ {+ minminlength++;+ }++ /* In the case of an anchored pattern, set up the value only if it follows+ a variable length item in the pattern. */++ if ((re->overall_options & PCRE2_ANCHORED) == 0 ||+ (reqcuflags & REQ_VARY) != 0)+ {+ re->last_codeunit = reqcu;+ re->flags |= PCRE2_LASTSET;++ /* Handle caseless required code units as for first code units (above). */++ if ((reqcuflags & REQ_CASELESS) != 0)+ {+ if (reqcu < 128 || (!utf && !ucp && reqcu < 255))+ {+ if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS;+ }+#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+ else if (ucp && !utf && UCD_OTHERCASE(reqcu) != reqcu)+ re->flags |= PCRE2_LASTCASELESS;+#else+ else if ((utf || ucp) && reqcu <= MAX_UTF_CODE_POINT &&+ UCD_OTHERCASE(reqcu) != reqcu)+ re->flags |= PCRE2_LASTCASELESS;+#endif+#endif /* SUPPORT_UNICODE */+ }+ }+ }++ /* Study the compiled pattern to set up information such as a bitmap of+ starting code units and a minimum matching length. */++ if (PRIV(study)(re) != 0)+ {+ errorcode = ERR31;+ goto HAD_CB_ERROR;+ }++ /* If study() set a bitmap of starting code units, it implies a minimum+ length of at least one. */++ if ((re->flags & PCRE2_FIRSTMAPSET) != 0 && minminlength == 0)+ minminlength = 1;++ /* If the minimum length set (or not set) by study() is less than the minimum+ implied by required code units, override it. */++ if (re->minlength < minminlength) re->minlength = minminlength;+ } /* End of start-of-match optimizations. */++/* Control ends up here in all cases. When running under valgrind, make a+pattern's terminating zero defined again. If memory was obtained for the parsed+version of the pattern, free it before returning. Also free the list of named+groups if a larger one had to be obtained, and likewise the group information+vector. */++EXIT:+#ifdef SUPPORT_VALGRIND+if (zero_terminated) VALGRIND_MAKE_MEM_DEFINED(pattern + patlen, CU2BYTES(1));+#endif+if (cb.parsed_pattern != stack_parsed_pattern)+ ccontext->memctl.free(cb.parsed_pattern, ccontext->memctl.memory_data);+if (cb.named_group_list_size > NAMED_GROUP_LIST_SIZE)+ ccontext->memctl.free((void *)cb.named_groups, ccontext->memctl.memory_data);+if (cb.groupinfo != stack_groupinfo)+ ccontext->memctl.free((void *)cb.groupinfo, ccontext->memctl.memory_data);+return re; /* Will be NULL after an error */++/* Errors discovered in parse_regex() set the offset value in the compile+block. Errors discovered before it is called must compute it from the ptr+value. After parse_regex() is called, the offset in the compile block is set to+the end of the pattern, but certain errors in compile_regex() may reset it if+an offset is available in the parsed pattern. */++HAD_CB_ERROR:+ptr = pattern + cb.erroroffset;++HAD_EARLY_ERROR:+*erroroffset = ptr - pattern;++HAD_ERROR:+*errorptr = errorcode;+pcre2_code_free(re);+re = NULL;+goto EXIT;+}++/* End of pcre2_compile.c */
+ src/c/pcre2/src/pcre2_config.c view
@@ -0,0 +1,252 @@+/*************************************************+* 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) 2016-2020 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++/* Save the configured link size, which is in bytes. In 16-bit and 32-bit modes+its value gets changed by pcre2_intmodedep.h (included by pcre2_internal.h) to+be in code units. */++static int configured_link_size = LINK_SIZE;++#include "pcre2_internal.h"++/* These macros are the standard way of turning unquoted text into C strings.+They allow macros like PCRE2_MAJOR to be defined without quotes, which is+convenient for user programs that want to test their values. */++#define STRING(a) # a+#define XSTRING(s) STRING(s)+++/*************************************************+* Return info about what features are configured *+*************************************************/++/* If where is NULL, the length of memory required is returned.++Arguments:+ what what information is required+ where where to put the information++Returns: 0 if a numerical value is returned+ >= 0 if a string value+ PCRE2_ERROR_BADOPTION if "where" not recognized+ or JIT target requested when JIT not enabled+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_config(uint32_t what, void *where)+{+if (where == NULL) /* Requests a length */+ {+ switch(what)+ {+ default:+ return PCRE2_ERROR_BADOPTION;++ case PCRE2_CONFIG_BSR:+ case PCRE2_CONFIG_COMPILED_WIDTHS:+ case PCRE2_CONFIG_DEPTHLIMIT:+ case PCRE2_CONFIG_HEAPLIMIT:+ case PCRE2_CONFIG_JIT:+ case PCRE2_CONFIG_LINKSIZE:+ case PCRE2_CONFIG_MATCHLIMIT:+ case PCRE2_CONFIG_NEVER_BACKSLASH_C:+ case PCRE2_CONFIG_NEWLINE:+ case PCRE2_CONFIG_PARENSLIMIT:+ case PCRE2_CONFIG_STACKRECURSE: /* Obsolete */+ case PCRE2_CONFIG_TABLES_LENGTH:+ case PCRE2_CONFIG_UNICODE:+ return sizeof(uint32_t);++ /* These are handled below */++ case PCRE2_CONFIG_JITTARGET:+ case PCRE2_CONFIG_UNICODE_VERSION:+ case PCRE2_CONFIG_VERSION:+ break;+ }+ }++switch (what)+ {+ default:+ return PCRE2_ERROR_BADOPTION;++ case PCRE2_CONFIG_BSR:+#ifdef BSR_ANYCRLF+ *((uint32_t *)where) = PCRE2_BSR_ANYCRLF;+#else+ *((uint32_t *)where) = PCRE2_BSR_UNICODE;+#endif+ break;++ case PCRE2_CONFIG_COMPILED_WIDTHS:+ *((uint32_t *)where) = 0+#ifdef SUPPORT_PCRE2_8+ + 1+#endif+#ifdef SUPPORT_PCRE2_16+ + 2+#endif+#ifdef SUPPORT_PCRE2_32+ + 4+#endif+ ;+ break;++ case PCRE2_CONFIG_DEPTHLIMIT:+ *((uint32_t *)where) = MATCH_LIMIT_DEPTH;+ break;++ case PCRE2_CONFIG_HEAPLIMIT:+ *((uint32_t *)where) = HEAP_LIMIT;+ break;++ case PCRE2_CONFIG_JIT:+#ifdef SUPPORT_JIT+ *((uint32_t *)where) = 1;+#else+ *((uint32_t *)where) = 0;+#endif+ break;++ case PCRE2_CONFIG_JITTARGET:+#ifdef SUPPORT_JIT+ {+ const char *v = PRIV(jit_get_target)();+ return (int)(1 + ((where == NULL)?+ strlen(v) : PRIV(strcpy_c8)((PCRE2_UCHAR *)where, v)));+ }+#else+ return PCRE2_ERROR_BADOPTION;+#endif++ case PCRE2_CONFIG_LINKSIZE:+ *((uint32_t *)where) = (uint32_t)configured_link_size;+ break;++ case PCRE2_CONFIG_MATCHLIMIT:+ *((uint32_t *)where) = MATCH_LIMIT;+ break;++ case PCRE2_CONFIG_NEWLINE:+ *((uint32_t *)where) = NEWLINE_DEFAULT;+ break;++ case PCRE2_CONFIG_NEVER_BACKSLASH_C:+#ifdef NEVER_BACKSLASH_C+ *((uint32_t *)where) = 1;+#else+ *((uint32_t *)where) = 0;+#endif+ break;++ case PCRE2_CONFIG_PARENSLIMIT:+ *((uint32_t *)where) = PARENS_NEST_LIMIT;+ break;++ /* This is now obsolete. The stack is no longer used via recursion for+ handling backtracking in pcre2_match(). */++ case PCRE2_CONFIG_STACKRECURSE:+ *((uint32_t *)where) = 0;+ break;++ case PCRE2_CONFIG_TABLES_LENGTH:+ *((uint32_t *)where) = TABLES_LENGTH;+ break;++ case PCRE2_CONFIG_UNICODE_VERSION:+ {+#if defined SUPPORT_UNICODE+ const char *v = PRIV(unicode_version);+#else+ const char *v = "Unicode not supported";+#endif+ return (int)(1 + ((where == NULL)?+ strlen(v) : PRIV(strcpy_c8)((PCRE2_UCHAR *)where, v)));+ }+ break;++ case PCRE2_CONFIG_UNICODE:+#if defined SUPPORT_UNICODE+ *((uint32_t *)where) = 1;+#else+ *((uint32_t *)where) = 0;+#endif+ break;++ /* The hackery in setting "v" below is to cope with the case when+ PCRE2_PRERELEASE is set to an empty string (which it is for real releases).+ If the second alternative is used in this case, it does not leave a space+ before the date. On the other hand, if all four macros are put into a single+ XSTRING when PCRE2_PRERELEASE is not empty, an unwanted space is inserted.+ There are problems using an "obvious" approach like this:++ XSTRING(PCRE2_MAJOR) "." XSTRING(PCRE_MINOR)+ XSTRING(PCRE2_PRERELEASE) " " XSTRING(PCRE_DATE)++ because, when PCRE2_PRERELEASE is empty, this leads to an attempted expansion+ of STRING(). The C standard states: "If (before argument substitution) any+ argument consists of no preprocessing tokens, the behavior is undefined." It+ turns out the gcc treats this case as a single empty string - which is what+ we really want - but Visual C grumbles about the lack of an argument for the+ macro. Unfortunately, both are within their rights. As there seems to be no+ way to test for a macro's value being empty at compile time, we have to+ resort to a runtime test. */++ case PCRE2_CONFIG_VERSION:+ {+ const char *v = (XSTRING(Z PCRE2_PRERELEASE)[1] == 0)?+ XSTRING(PCRE2_MAJOR.PCRE2_MINOR PCRE2_DATE) :+ XSTRING(PCRE2_MAJOR.PCRE2_MINOR) XSTRING(PCRE2_PRERELEASE PCRE2_DATE);+ return (int)(1 + ((where == NULL)?+ strlen(v) : PRIV(strcpy_c8)((PCRE2_UCHAR *)where, v)));+ }+ }++return 0;+}++/* End of pcre2_config.c */
+ src/c/pcre2/src/pcre2_context.c view
@@ -0,0 +1,488 @@+/*************************************************+* 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) 2016-2018 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++#include "pcre2_internal.h"++++/*************************************************+* Default malloc/free functions *+*************************************************/++/* Ignore the "user data" argument in each case. */++static void *default_malloc(size_t size, void *data)+{+(void)data;+return malloc(size);+}+++static void default_free(void *block, void *data)+{+(void)data;+free(block);+}++++/*************************************************+* Get a block and save memory control *+*************************************************/++/* This internal function is called to get a block of memory in which the+memory control data is to be stored at the start for future use.++Arguments:+ size amount of memory required+ memctl pointer to a memctl block or NULL++Returns: pointer to memory or NULL on failure+*/++extern void *+PRIV(memctl_malloc)(size_t size, pcre2_memctl *memctl)+{+pcre2_memctl *newmemctl;+void *yield = (memctl == NULL)? malloc(size) :+ memctl->malloc(size, memctl->memory_data);+if (yield == NULL) return NULL;+newmemctl = (pcre2_memctl *)yield;+if (memctl == NULL)+ {+ newmemctl->malloc = default_malloc;+ newmemctl->free = default_free;+ newmemctl->memory_data = NULL;+ }+else *newmemctl = *memctl;+return yield;+}++++/*************************************************+* Create and initialize contexts *+*************************************************/++/* Initializing for compile and match contexts is done in separate, private+functions so that these can be called from functions such as pcre2_compile()+when an external context is not supplied. The initializing functions have an+option to set up default memory management. */++PCRE2_EXP_DEFN pcre2_general_context * PCRE2_CALL_CONVENTION+pcre2_general_context_create(void *(*private_malloc)(size_t, void *),+ void (*private_free)(void *, void *), void *memory_data)+{+pcre2_general_context *gcontext;+if (private_malloc == NULL) private_malloc = default_malloc;+if (private_free == NULL) private_free = default_free;+gcontext = private_malloc(sizeof(pcre2_real_general_context), memory_data);+if (gcontext == NULL) return NULL;+gcontext->memctl.malloc = private_malloc;+gcontext->memctl.free = private_free;+gcontext->memctl.memory_data = memory_data;+return gcontext;+}+++/* A default compile context is set up to save having to initialize at run time+when no context is supplied to the compile function. */++const pcre2_compile_context PRIV(default_compile_context) = {+ { default_malloc, default_free, NULL }, /* Default memory handling */+ NULL, /* Stack guard */+ NULL, /* Stack guard data */+ PRIV(default_tables), /* Character tables */+ PCRE2_UNSET, /* Max pattern length */+ BSR_DEFAULT, /* Backslash R default */+ NEWLINE_DEFAULT, /* Newline convention */+ PARENS_NEST_LIMIT, /* As it says */+ 0 }; /* Extra options */++/* The create function copies the default into the new memory, but must+override the default memory handling functions if a gcontext was provided. */++PCRE2_EXP_DEFN pcre2_compile_context * PCRE2_CALL_CONVENTION+pcre2_compile_context_create(pcre2_general_context *gcontext)+{+pcre2_compile_context *ccontext = PRIV(memctl_malloc)(+ sizeof(pcre2_real_compile_context), (pcre2_memctl *)gcontext);+if (ccontext == NULL) return NULL;+*ccontext = PRIV(default_compile_context);+if (gcontext != NULL)+ *((pcre2_memctl *)ccontext) = *((pcre2_memctl *)gcontext);+return ccontext;+}+++/* A default match context is set up to save having to initialize at run time+when no context is supplied to a match function. */++const pcre2_match_context PRIV(default_match_context) = {+ { default_malloc, default_free, NULL },+#ifdef SUPPORT_JIT+ NULL, /* JIT callback */+ NULL, /* JIT callback data */+#endif+ NULL, /* Callout function */+ NULL, /* Callout data */+ NULL, /* Substitute callout function */+ NULL, /* Substitute callout data */+ PCRE2_UNSET, /* Offset limit */+ HEAP_LIMIT,+ MATCH_LIMIT,+ MATCH_LIMIT_DEPTH };++/* The create function copies the default into the new memory, but must+override the default memory handling functions if a gcontext was provided. */++PCRE2_EXP_DEFN pcre2_match_context * PCRE2_CALL_CONVENTION+pcre2_match_context_create(pcre2_general_context *gcontext)+{+pcre2_match_context *mcontext = PRIV(memctl_malloc)(+ sizeof(pcre2_real_match_context), (pcre2_memctl *)gcontext);+if (mcontext == NULL) return NULL;+*mcontext = PRIV(default_match_context);+if (gcontext != NULL)+ *((pcre2_memctl *)mcontext) = *((pcre2_memctl *)gcontext);+return mcontext;+}+++/* A default convert context is set up to save having to initialize at run time+when no context is supplied to the convert function. */++const pcre2_convert_context PRIV(default_convert_context) = {+ { default_malloc, default_free, NULL }, /* Default memory handling */+#ifdef _WIN32+ CHAR_BACKSLASH, /* Default path separator */+ CHAR_GRAVE_ACCENT /* Default escape character */+#else /* Not Windows */+ CHAR_SLASH, /* Default path separator */+ CHAR_BACKSLASH /* Default escape character */+#endif+ };++/* The create function copies the default into the new memory, but must+override the default memory handling functions if a gcontext was provided. */++PCRE2_EXP_DEFN pcre2_convert_context * PCRE2_CALL_CONVENTION+pcre2_convert_context_create(pcre2_general_context *gcontext)+{+pcre2_convert_context *ccontext = PRIV(memctl_malloc)(+ sizeof(pcre2_real_convert_context), (pcre2_memctl *)gcontext);+if (ccontext == NULL) return NULL;+*ccontext = PRIV(default_convert_context);+if (gcontext != NULL)+ *((pcre2_memctl *)ccontext) = *((pcre2_memctl *)gcontext);+return ccontext;+}+++/*************************************************+* Context copy functions *+*************************************************/++PCRE2_EXP_DEFN pcre2_general_context * PCRE2_CALL_CONVENTION+pcre2_general_context_copy(pcre2_general_context *gcontext)+{+pcre2_general_context *new =+ gcontext->memctl.malloc(sizeof(pcre2_real_general_context),+ gcontext->memctl.memory_data);+if (new == NULL) return NULL;+memcpy(new, gcontext, sizeof(pcre2_real_general_context));+return new;+}+++PCRE2_EXP_DEFN pcre2_compile_context * PCRE2_CALL_CONVENTION+pcre2_compile_context_copy(pcre2_compile_context *ccontext)+{+pcre2_compile_context *new =+ ccontext->memctl.malloc(sizeof(pcre2_real_compile_context),+ ccontext->memctl.memory_data);+if (new == NULL) return NULL;+memcpy(new, ccontext, sizeof(pcre2_real_compile_context));+return new;+}+++PCRE2_EXP_DEFN pcre2_match_context * PCRE2_CALL_CONVENTION+pcre2_match_context_copy(pcre2_match_context *mcontext)+{+pcre2_match_context *new =+ mcontext->memctl.malloc(sizeof(pcre2_real_match_context),+ mcontext->memctl.memory_data);+if (new == NULL) return NULL;+memcpy(new, mcontext, sizeof(pcre2_real_match_context));+return new;+}++++PCRE2_EXP_DEFN pcre2_convert_context * PCRE2_CALL_CONVENTION+pcre2_convert_context_copy(pcre2_convert_context *ccontext)+{+pcre2_convert_context *new =+ ccontext->memctl.malloc(sizeof(pcre2_real_convert_context),+ ccontext->memctl.memory_data);+if (new == NULL) return NULL;+memcpy(new, ccontext, sizeof(pcre2_real_convert_context));+return new;+}+++/*************************************************+* Context free functions *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_general_context_free(pcre2_general_context *gcontext)+{+if (gcontext != NULL)+ gcontext->memctl.free(gcontext, gcontext->memctl.memory_data);+}+++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_compile_context_free(pcre2_compile_context *ccontext)+{+if (ccontext != NULL)+ ccontext->memctl.free(ccontext, ccontext->memctl.memory_data);+}+++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_match_context_free(pcre2_match_context *mcontext)+{+if (mcontext != NULL)+ mcontext->memctl.free(mcontext, mcontext->memctl.memory_data);+}+++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_convert_context_free(pcre2_convert_context *ccontext)+{+if (ccontext != NULL)+ ccontext->memctl.free(ccontext, ccontext->memctl.memory_data);+}+++/*************************************************+* Set values in contexts *+*************************************************/++/* All these functions return 0 for success or PCRE2_ERROR_BADDATA if invalid+data is given. Only some of the functions are able to test the validity of the+data. */+++/* ------------ Compile context ------------ */++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_character_tables(pcre2_compile_context *ccontext,+ const uint8_t *tables)+{+ccontext->tables = tables;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_bsr(pcre2_compile_context *ccontext, uint32_t value)+{+switch(value)+ {+ case PCRE2_BSR_ANYCRLF:+ case PCRE2_BSR_UNICODE:+ ccontext->bsr_convention = value;+ return 0;++ default:+ return PCRE2_ERROR_BADDATA;+ }+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_max_pattern_length(pcre2_compile_context *ccontext, PCRE2_SIZE length)+{+ccontext->max_pattern_length = length;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_newline(pcre2_compile_context *ccontext, uint32_t newline)+{+switch(newline)+ {+ case PCRE2_NEWLINE_CR:+ case PCRE2_NEWLINE_LF:+ case PCRE2_NEWLINE_CRLF:+ case PCRE2_NEWLINE_ANY:+ case PCRE2_NEWLINE_ANYCRLF:+ case PCRE2_NEWLINE_NUL:+ ccontext->newline_convention = newline;+ return 0;++ default:+ return PCRE2_ERROR_BADDATA;+ }+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext, uint32_t limit)+{+ccontext->parens_nest_limit = limit;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_compile_extra_options(pcre2_compile_context *ccontext, uint32_t options)+{+ccontext->extra_options = options;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_compile_recursion_guard(pcre2_compile_context *ccontext,+ int (*guard)(uint32_t, void *), void *user_data)+{+ccontext->stack_guard = guard;+ccontext->stack_guard_data = user_data;+return 0;+}+++/* ------------ Match context ------------ */++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_callout(pcre2_match_context *mcontext,+ int (*callout)(pcre2_callout_block *, void *), void *callout_data)+{+mcontext->callout = callout;+mcontext->callout_data = callout_data;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_substitute_callout(pcre2_match_context *mcontext,+ int (*substitute_callout)(pcre2_substitute_callout_block *, void *),+ void *substitute_callout_data)+{+mcontext->substitute_callout = substitute_callout;+mcontext->substitute_callout_data = substitute_callout_data;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_heap_limit(pcre2_match_context *mcontext, uint32_t limit)+{+mcontext->heap_limit = limit;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_match_limit(pcre2_match_context *mcontext, uint32_t limit)+{+mcontext->match_limit = limit;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_depth_limit(pcre2_match_context *mcontext, uint32_t limit)+{+mcontext->depth_limit = limit;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_offset_limit(pcre2_match_context *mcontext, PCRE2_SIZE limit)+{+mcontext->offset_limit = limit;+return 0;+}++/* This function became obsolete at release 10.30. It is kept as a synonym for+backwards compatibility. */++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_recursion_limit(pcre2_match_context *mcontext, uint32_t limit)+{+return pcre2_set_depth_limit(mcontext, limit);+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_recursion_memory_management(pcre2_match_context *mcontext,+ void *(*mymalloc)(size_t, void *), void (*myfree)(void *, void *),+ void *mydata)+{+(void)mcontext;+(void)mymalloc;+(void)myfree;+(void)mydata;+return 0;+}++/* ------------ Convert context ------------ */++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_glob_separator(pcre2_convert_context *ccontext, uint32_t separator)+{+if (separator != CHAR_SLASH && separator != CHAR_BACKSLASH &&+ separator != CHAR_DOT) return PCRE2_ERROR_BADDATA;+ccontext->glob_separator = separator;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_glob_escape(pcre2_convert_context *ccontext, uint32_t escape)+{+if (escape > 255 || (escape != 0 && !ispunct(escape)))+ return PCRE2_ERROR_BADDATA;+ccontext->glob_escape = escape;+return 0;+}++/* End of pcre2_context.c */+
+ src/c/pcre2/src/pcre2_convert.c view
@@ -0,0 +1,1182 @@+/*************************************************+* 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) 2016-2018 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++#include "pcre2_internal.h"++#define TYPE_OPTIONS (PCRE2_CONVERT_GLOB| \+ PCRE2_CONVERT_POSIX_BASIC|PCRE2_CONVERT_POSIX_EXTENDED)++#define ALL_OPTIONS (PCRE2_CONVERT_UTF|PCRE2_CONVERT_NO_UTF_CHECK| \+ PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR| \+ PCRE2_CONVERT_GLOB_NO_STARSTAR| \+ TYPE_OPTIONS)++#define DUMMY_BUFFER_SIZE 100++/* Generated pattern fragments */++#define STR_BACKSLASH_A STR_BACKSLASH STR_A+#define STR_BACKSLASH_z STR_BACKSLASH STR_z+#define STR_COLON_RIGHT_SQUARE_BRACKET STR_COLON STR_RIGHT_SQUARE_BRACKET+#define STR_DOT_STAR_LOOKBEHIND STR_DOT STR_ASTERISK STR_LEFT_PARENTHESIS STR_QUESTION_MARK STR_LESS_THAN_SIGN STR_EQUALS_SIGN+#define STR_LOOKAHEAD_NOT_DOT STR_LEFT_PARENTHESIS STR_QUESTION_MARK STR_EXCLAMATION_MARK STR_BACKSLASH STR_DOT STR_RIGHT_PARENTHESIS+#define STR_QUERY_s STR_LEFT_PARENTHESIS STR_QUESTION_MARK STR_s STR_RIGHT_PARENTHESIS+#define STR_STAR_NUL STR_LEFT_PARENTHESIS STR_ASTERISK STR_N STR_U STR_L STR_RIGHT_PARENTHESIS++/* States for range and POSIX processing */++enum { RANGE_NOT_STARTED, RANGE_STARTING, RANGE_STARTED };+enum { POSIX_START_REGEX, POSIX_ANCHORED, POSIX_NOT_BRACKET,+ POSIX_CLASS_NOT_STARTED, POSIX_CLASS_STARTING, POSIX_CLASS_STARTED };++/* Macro to add a character string to the output buffer, checking for overflow. */++#define PUTCHARS(string) \+ { \+ for (s = (char *)(string); *s != 0; s++) \+ { \+ if (p >= endp) return PCRE2_ERROR_NOMEMORY; \+ *p++ = *s; \+ } \+ }++/* Literals that must be escaped: \ ? * + | . ^ $ { } [ ] ( ) */++static const char *pcre2_escaped_literals =+ STR_BACKSLASH STR_QUESTION_MARK STR_ASTERISK STR_PLUS+ STR_VERTICAL_LINE STR_DOT STR_CIRCUMFLEX_ACCENT STR_DOLLAR_SIGN+ STR_LEFT_CURLY_BRACKET STR_RIGHT_CURLY_BRACKET+ STR_LEFT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET+ STR_LEFT_PARENTHESIS STR_RIGHT_PARENTHESIS;++/* Recognized escaped metacharacters in POSIX basic patterns. */++static const char *posix_meta_escapes =+ STR_LEFT_PARENTHESIS STR_RIGHT_PARENTHESIS+ STR_LEFT_CURLY_BRACKET STR_RIGHT_CURLY_BRACKET+ STR_1 STR_2 STR_3 STR_4 STR_5 STR_6 STR_7 STR_8 STR_9;++++/*************************************************+* Convert a POSIX pattern *+*************************************************/++/* This function handles both basic and extended POSIX patterns.++Arguments:+ pattype the pattern type+ pattern the pattern+ plength length in code units+ utf TRUE if UTF+ use_buffer where to put the output+ use_length length of use_buffer+ bufflenptr where to put the used length+ dummyrun TRUE if a dummy run+ ccontext the convert context++Returns: 0 => success+ !0 => error code+*/++static int+convert_posix(uint32_t pattype, PCRE2_SPTR pattern, PCRE2_SIZE plength,+ BOOL utf, PCRE2_UCHAR *use_buffer, PCRE2_SIZE use_length,+ PCRE2_SIZE *bufflenptr, BOOL dummyrun, pcre2_convert_context *ccontext)+{+char *s;+PCRE2_SPTR posix = pattern;+PCRE2_UCHAR *p = use_buffer;+PCRE2_UCHAR *pp = p;+PCRE2_UCHAR *endp = p + use_length - 1; /* Allow for trailing zero */+PCRE2_SIZE convlength = 0;++uint32_t bracount = 0;+uint32_t posix_state = POSIX_START_REGEX;+uint32_t lastspecial = 0;+BOOL extended = (pattype & PCRE2_CONVERT_POSIX_EXTENDED) != 0;+BOOL nextisliteral = FALSE;++(void)utf; /* Not used when Unicode not supported */+(void)ccontext; /* Not currently used */++/* Initialize default for error offset as end of input. */++*bufflenptr = plength;+PUTCHARS(STR_STAR_NUL);++/* Now scan the input. */++while (plength > 0)+ {+ uint32_t c, sc;+ int clength = 1;++ /* Add in the length of the last item, then, if in the dummy run, pull the+ pointer back to the start of the (temporary) buffer and then remember the+ start of the next item. */++ convlength += p - pp;+ if (dummyrun) p = use_buffer;+ pp = p;++ /* Pick up the next character */++#ifndef SUPPORT_UNICODE+ c = *posix;+#else+ GETCHARLENTEST(c, posix, clength);+#endif+ posix += clength;+ plength -= clength;++ sc = nextisliteral? 0 : c;+ nextisliteral = FALSE;++ /* Handle a character within a class. */++ if (posix_state >= POSIX_CLASS_NOT_STARTED)+ {+ if (c == CHAR_RIGHT_SQUARE_BRACKET)+ {+ PUTCHARS(STR_RIGHT_SQUARE_BRACKET);+ posix_state = POSIX_NOT_BRACKET;+ }++ /* Not the end of the class */++ else+ {+ switch (posix_state)+ {+ case POSIX_CLASS_STARTED:+ if (c <= 127 && islower(c)) break; /* Remain in started state */+ posix_state = POSIX_CLASS_NOT_STARTED;+ if (c == CHAR_COLON && plength > 0 &&+ *posix == CHAR_RIGHT_SQUARE_BRACKET)+ {+ PUTCHARS(STR_COLON_RIGHT_SQUARE_BRACKET);+ plength--;+ posix++;+ continue; /* With next character after :] */+ }+ /* Fall through */++ case POSIX_CLASS_NOT_STARTED:+ if (c == CHAR_LEFT_SQUARE_BRACKET)+ posix_state = POSIX_CLASS_STARTING;+ break;++ case POSIX_CLASS_STARTING:+ if (c == CHAR_COLON) posix_state = POSIX_CLASS_STARTED;+ break;+ }++ if (c == CHAR_BACKSLASH) PUTCHARS(STR_BACKSLASH);+ if (p + clength > endp) return PCRE2_ERROR_NOMEMORY;+ memcpy(p, posix - clength, CU2BYTES(clength));+ p += clength;+ }+ }++ /* Handle a character not within a class. */++ else switch(sc)+ {+ case CHAR_LEFT_SQUARE_BRACKET:+ PUTCHARS(STR_LEFT_SQUARE_BRACKET);++#ifdef NEVER+ /* We could handle special cases [[:<:]] and [[:>:]] (which PCRE does+ support) but they are not part of POSIX 1003.1. */++ if (plength >= 6)+ {+ if (posix[0] == CHAR_LEFT_SQUARE_BRACKET &&+ posix[1] == CHAR_COLON &&+ (posix[2] == CHAR_LESS_THAN_SIGN ||+ posix[2] == CHAR_GREATER_THAN_SIGN) &&+ posix[3] == CHAR_COLON &&+ posix[4] == CHAR_RIGHT_SQUARE_BRACKET &&+ posix[5] == CHAR_RIGHT_SQUARE_BRACKET)+ {+ if (p + 6 > endp) return PCRE2_ERROR_NOMEMORY;+ memcpy(p, posix, CU2BYTES(6));+ p += 6;+ posix += 6;+ plength -= 6;+ continue; /* With next character */+ }+ }+#endif++ /* Handle start of "normal" character classes */++ posix_state = POSIX_CLASS_NOT_STARTED;++ /* Handle ^ and ] as first characters */++ if (plength > 0)+ {+ if (*posix == CHAR_CIRCUMFLEX_ACCENT)+ {+ posix++;+ plength--;+ PUTCHARS(STR_CIRCUMFLEX_ACCENT);+ }+ if (plength > 0 && *posix == CHAR_RIGHT_SQUARE_BRACKET)+ {+ posix++;+ plength--;+ PUTCHARS(STR_RIGHT_SQUARE_BRACKET);+ }+ }+ break;++ case CHAR_BACKSLASH:+ if (plength == 0) return PCRE2_ERROR_END_BACKSLASH;+ if (extended) nextisliteral = TRUE; else+ {+ if (*posix < 127 && strchr(posix_meta_escapes, *posix) != NULL)+ {+ if (isdigit(*posix)) PUTCHARS(STR_BACKSLASH);+ if (p + 1 > endp) return PCRE2_ERROR_NOMEMORY;+ lastspecial = *p++ = *posix++;+ plength--;+ }+ else nextisliteral = TRUE;+ }+ break;++ case CHAR_RIGHT_PARENTHESIS:+ if (!extended || bracount == 0) goto ESCAPE_LITERAL;+ bracount--;+ goto COPY_SPECIAL;++ case CHAR_LEFT_PARENTHESIS:+ bracount++;+ /* Fall through */++ case CHAR_QUESTION_MARK:+ case CHAR_PLUS:+ case CHAR_LEFT_CURLY_BRACKET:+ case CHAR_RIGHT_CURLY_BRACKET:+ case CHAR_VERTICAL_LINE:+ if (!extended) goto ESCAPE_LITERAL;+ /* Fall through */++ case CHAR_DOT:+ case CHAR_DOLLAR_SIGN:+ posix_state = POSIX_NOT_BRACKET;+ COPY_SPECIAL:+ lastspecial = c;+ if (p + 1 > endp) return PCRE2_ERROR_NOMEMORY;+ *p++ = c;+ break;++ case CHAR_ASTERISK:+ if (lastspecial != CHAR_ASTERISK)+ {+ if (!extended && (posix_state < POSIX_NOT_BRACKET ||+ lastspecial == CHAR_LEFT_PARENTHESIS))+ goto ESCAPE_LITERAL;+ goto COPY_SPECIAL;+ }+ break; /* Ignore second and subsequent asterisks */++ case CHAR_CIRCUMFLEX_ACCENT:+ if (extended) goto COPY_SPECIAL;+ if (posix_state == POSIX_START_REGEX ||+ lastspecial == CHAR_LEFT_PARENTHESIS)+ {+ posix_state = POSIX_ANCHORED;+ goto COPY_SPECIAL;+ }+ /* Fall through */++ default:+ if (c < 128 && strchr(pcre2_escaped_literals, c) != NULL)+ {+ ESCAPE_LITERAL:+ PUTCHARS(STR_BACKSLASH);+ }+ lastspecial = 0xff; /* Indicates nothing special */+ if (p + clength > endp) return PCRE2_ERROR_NOMEMORY;+ memcpy(p, posix - clength, CU2BYTES(clength));+ p += clength;+ posix_state = POSIX_NOT_BRACKET;+ break;+ }+ }++if (posix_state >= POSIX_CLASS_NOT_STARTED)+ return PCRE2_ERROR_MISSING_SQUARE_BRACKET;+convlength += p - pp; /* Final segment */+*bufflenptr = convlength;+*p++ = 0;+return 0;+}+++/*************************************************+* Convert a glob pattern *+*************************************************/++/* Context for writing the output into a buffer. */++typedef struct pcre2_output_context {+ PCRE2_UCHAR *output; /* current output position */+ PCRE2_SPTR output_end; /* output end */+ PCRE2_SIZE output_size; /* size of the output */+ uint8_t out_str[8]; /* string copied to the output */+} pcre2_output_context;+++/* Write a character into the output.++Arguments:+ out output context+ chr the next character+*/++static void+convert_glob_write(pcre2_output_context *out, PCRE2_UCHAR chr)+{+out->output_size++;++if (out->output < out->output_end)+ *out->output++ = chr;+}+++/* Write a string into the output.++Arguments:+ out output context+ length length of out->out_str+*/++static void+convert_glob_write_str(pcre2_output_context *out, PCRE2_SIZE length)+{+uint8_t *out_str = out->out_str;+PCRE2_UCHAR *output = out->output;+PCRE2_SPTR output_end = out->output_end;+PCRE2_SIZE output_size = out->output_size;++do+ {+ output_size++;++ if (output < output_end)+ *output++ = *out_str++;+ }+while (--length != 0);++out->output = output;+out->output_size = output_size;+}+++/* Prints the separator into the output.++Arguments:+ out output context+ separator glob separator+ with_escape backslash is needed before separator+*/++static void+convert_glob_print_separator(pcre2_output_context *out,+ PCRE2_UCHAR separator, BOOL with_escape)+{+if (with_escape)+ convert_glob_write(out, CHAR_BACKSLASH);++convert_glob_write(out, separator);+}+++/* Prints a wildcard into the output.++Arguments:+ out output context+ separator glob separator+ with_escape backslash is needed before separator+*/++static void+convert_glob_print_wildcard(pcre2_output_context *out,+ PCRE2_UCHAR separator, BOOL with_escape)+{+out->out_str[0] = CHAR_LEFT_SQUARE_BRACKET;+out->out_str[1] = CHAR_CIRCUMFLEX_ACCENT;+convert_glob_write_str(out, 2);++convert_glob_print_separator(out, separator, with_escape);++convert_glob_write(out, CHAR_RIGHT_SQUARE_BRACKET);+}+++/* Parse a posix class.++Arguments:+ from starting point of scanning the range+ pattern_end end of pattern+ out output context++Returns: >0 => class index+ 0 => malformed class+*/++static int+convert_glob_parse_class(PCRE2_SPTR *from, PCRE2_SPTR pattern_end,+ pcre2_output_context *out)+{+static const char *posix_classes = "alnum:alpha:ascii:blank:cntrl:digit:"+ "graph:lower:print:punct:space:upper:word:xdigit:";+PCRE2_SPTR start = *from + 1;+PCRE2_SPTR pattern = start;+const char *class_ptr;+PCRE2_UCHAR c;+int class_index;++while (TRUE)+ {+ if (pattern >= pattern_end) return 0;++ c = *pattern++;++ if (c < CHAR_a || c > CHAR_z) break;+ }++if (c != CHAR_COLON || pattern >= pattern_end ||+ *pattern != CHAR_RIGHT_SQUARE_BRACKET)+ return 0;++class_ptr = posix_classes;+class_index = 1;++while (TRUE)+ {+ if (*class_ptr == CHAR_NUL) return 0;++ pattern = start;++ while (*pattern == (PCRE2_UCHAR) *class_ptr)+ {+ if (*pattern == CHAR_COLON)+ {+ pattern += 2;+ start -= 2;++ do convert_glob_write(out, *start++); while (start < pattern);++ *from = pattern;+ return class_index;+ }+ pattern++;+ class_ptr++;+ }++ while (*class_ptr != CHAR_COLON) class_ptr++;+ class_ptr++;+ class_index++;+ }+}++/* Checks whether the character is in the class.++Arguments:+ class_index class index+ c character++Returns: !0 => character is found in the class+ 0 => otherwise+*/++static BOOL+convert_glob_char_in_class(int class_index, PCRE2_UCHAR c)+{+switch (class_index)+ {+ case 1: return isalnum(c);+ case 2: return isalpha(c);+ case 3: return 1;+ case 4: return c == CHAR_HT || c == CHAR_SPACE;+ case 5: return iscntrl(c);+ case 6: return isdigit(c);+ case 7: return isgraph(c);+ case 8: return islower(c);+ case 9: return isprint(c);+ case 10: return ispunct(c);+ case 11: return isspace(c);+ case 12: return isupper(c);+ case 13: return isalnum(c) || c == CHAR_UNDERSCORE;+ default: return isxdigit(c);+ }+}++/* Parse a range of characters.++Arguments:+ from starting point of scanning the range+ pattern_end end of pattern+ out output context+ separator glob separator+ with_escape backslash is needed before separator++Returns: 0 => success+ !0 => error code+*/++static int+convert_glob_parse_range(PCRE2_SPTR *from, PCRE2_SPTR pattern_end,+ pcre2_output_context *out, BOOL utf, PCRE2_UCHAR separator,+ BOOL with_escape, PCRE2_UCHAR escape, BOOL no_wildsep)+{+BOOL is_negative = FALSE;+BOOL separator_seen = FALSE;+BOOL has_prev_c;+PCRE2_SPTR pattern = *from;+PCRE2_SPTR char_start = NULL;+uint32_t c, prev_c;+int len, class_index;++(void)utf; /* Avoid compiler warning. */++if (pattern >= pattern_end)+ {+ *from = pattern;+ return PCRE2_ERROR_MISSING_SQUARE_BRACKET;+ }++if (*pattern == CHAR_EXCLAMATION_MARK+ || *pattern == CHAR_CIRCUMFLEX_ACCENT)+ {+ pattern++;++ if (pattern >= pattern_end)+ {+ *from = pattern;+ return PCRE2_ERROR_MISSING_SQUARE_BRACKET;+ }++ is_negative = TRUE;++ out->out_str[0] = CHAR_LEFT_SQUARE_BRACKET;+ out->out_str[1] = CHAR_CIRCUMFLEX_ACCENT;+ len = 2;++ if (!no_wildsep)+ {+ if (with_escape)+ {+ out->out_str[len] = CHAR_BACKSLASH;+ len++;+ }+ out->out_str[len] = (uint8_t) separator;+ }++ convert_glob_write_str(out, len + 1);+ }+else+ convert_glob_write(out, CHAR_LEFT_SQUARE_BRACKET);++has_prev_c = FALSE;+prev_c = 0;++if (*pattern == CHAR_RIGHT_SQUARE_BRACKET)+ {+ out->out_str[0] = CHAR_BACKSLASH;+ out->out_str[1] = CHAR_RIGHT_SQUARE_BRACKET;+ convert_glob_write_str(out, 2);+ has_prev_c = TRUE;+ prev_c = CHAR_RIGHT_SQUARE_BRACKET;+ pattern++;+ }++while (pattern < pattern_end)+ {+ char_start = pattern;+ GETCHARINCTEST(c, pattern);++ if (c == CHAR_RIGHT_SQUARE_BRACKET)+ {+ convert_glob_write(out, c);++ if (!is_negative && !no_wildsep && separator_seen)+ {+ out->out_str[0] = CHAR_LEFT_PARENTHESIS;+ out->out_str[1] = CHAR_QUESTION_MARK;+ out->out_str[2] = CHAR_LESS_THAN_SIGN;+ out->out_str[3] = CHAR_EXCLAMATION_MARK;+ convert_glob_write_str(out, 4);++ convert_glob_print_separator(out, separator, with_escape);+ convert_glob_write(out, CHAR_RIGHT_PARENTHESIS);+ }++ *from = pattern;+ return 0;+ }++ if (pattern >= pattern_end) break;++ if (c == CHAR_LEFT_SQUARE_BRACKET && *pattern == CHAR_COLON)+ {+ *from = pattern;+ class_index = convert_glob_parse_class(from, pattern_end, out);++ if (class_index != 0)+ {+ pattern = *from;++ has_prev_c = FALSE;+ prev_c = 0;++ if (!is_negative &&+ convert_glob_char_in_class (class_index, separator))+ separator_seen = TRUE;+ continue;+ }+ }+ else if (c == CHAR_MINUS && has_prev_c &&+ *pattern != CHAR_RIGHT_SQUARE_BRACKET)+ {+ convert_glob_write(out, CHAR_MINUS);++ char_start = pattern;+ GETCHARINCTEST(c, pattern);++ if (pattern >= pattern_end) break;++ if (escape != 0 && c == escape)+ {+ char_start = pattern;+ GETCHARINCTEST(c, pattern);+ }+ else if (c == CHAR_LEFT_SQUARE_BRACKET && *pattern == CHAR_COLON)+ {+ *from = pattern;+ return PCRE2_ERROR_CONVERT_SYNTAX;+ }++ if (prev_c > c)+ {+ *from = pattern;+ return PCRE2_ERROR_CONVERT_SYNTAX;+ }++ if (prev_c < separator && separator < c) separator_seen = TRUE;++ has_prev_c = FALSE;+ prev_c = 0;+ }+ else+ {+ if (escape != 0 && c == escape)+ {+ char_start = pattern;+ GETCHARINCTEST(c, pattern);++ if (pattern >= pattern_end) break;+ }++ has_prev_c = TRUE;+ prev_c = c;+ }++ if (c == CHAR_LEFT_SQUARE_BRACKET || c == CHAR_RIGHT_SQUARE_BRACKET ||+ c == CHAR_BACKSLASH || c == CHAR_MINUS)+ convert_glob_write(out, CHAR_BACKSLASH);++ if (c == separator) separator_seen = TRUE;++ do convert_glob_write(out, *char_start++); while (char_start < pattern);+ }++*from = pattern;+return PCRE2_ERROR_MISSING_SQUARE_BRACKET;+}+++/* Prints a (*COMMIT) into the output.++Arguments:+ out output context+*/++static void+convert_glob_print_commit(pcre2_output_context *out)+{+out->out_str[0] = CHAR_LEFT_PARENTHESIS;+out->out_str[1] = CHAR_ASTERISK;+out->out_str[2] = CHAR_C;+out->out_str[3] = CHAR_O;+out->out_str[4] = CHAR_M;+out->out_str[5] = CHAR_M;+out->out_str[6] = CHAR_I;+out->out_str[7] = CHAR_T;+convert_glob_write_str(out, 8);+convert_glob_write(out, CHAR_RIGHT_PARENTHESIS);+}+++/* Bash glob converter.++Arguments:+ pattype the pattern type+ pattern the pattern+ plength length in code units+ utf TRUE if UTF+ use_buffer where to put the output+ use_length length of use_buffer+ bufflenptr where to put the used length+ dummyrun TRUE if a dummy run+ ccontext the convert context++Returns: 0 => success+ !0 => error code+*/++static int+convert_glob(uint32_t options, PCRE2_SPTR pattern, PCRE2_SIZE plength,+ BOOL utf, PCRE2_UCHAR *use_buffer, PCRE2_SIZE use_length,+ PCRE2_SIZE *bufflenptr, BOOL dummyrun, pcre2_convert_context *ccontext)+{+pcre2_output_context out;+PCRE2_SPTR pattern_start = pattern;+PCRE2_SPTR pattern_end = pattern + plength;+PCRE2_UCHAR separator = ccontext->glob_separator;+PCRE2_UCHAR escape = ccontext->glob_escape;+PCRE2_UCHAR c;+BOOL no_wildsep = (options & PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR) != 0;+BOOL no_starstar = (options & PCRE2_CONVERT_GLOB_NO_STARSTAR) != 0;+BOOL in_atomic = FALSE;+BOOL after_starstar = FALSE;+BOOL no_slash_z = FALSE;+BOOL with_escape, is_start, after_separator;+int result = 0;++(void)utf; /* Avoid compiler warning. */++#ifdef SUPPORT_UNICODE+if (utf && (separator >= 128 || escape >= 128))+ {+ /* Currently only ASCII characters are supported. */+ *bufflenptr = 0;+ return PCRE2_ERROR_CONVERT_SYNTAX;+ }+#endif++with_escape = strchr(pcre2_escaped_literals, separator) != NULL;++/* Initialize default for error offset as end of input. */+out.output = use_buffer;+out.output_end = use_buffer + use_length;+out.output_size = 0;++out.out_str[0] = CHAR_LEFT_PARENTHESIS;+out.out_str[1] = CHAR_QUESTION_MARK;+out.out_str[2] = CHAR_s;+out.out_str[3] = CHAR_RIGHT_PARENTHESIS;+convert_glob_write_str(&out, 4);++is_start = TRUE;++if (pattern < pattern_end && pattern[0] == CHAR_ASTERISK)+ {+ if (no_wildsep)+ is_start = FALSE;+ else if (!no_starstar && pattern + 1 < pattern_end &&+ pattern[1] == CHAR_ASTERISK)+ is_start = FALSE;+ }++if (is_start)+ {+ out.out_str[0] = CHAR_BACKSLASH;+ out.out_str[1] = CHAR_A;+ convert_glob_write_str(&out, 2);+ }++while (pattern < pattern_end)+ {+ c = *pattern++;++ if (c == CHAR_ASTERISK)+ {+ is_start = pattern == pattern_start + 1;++ if (in_atomic)+ {+ convert_glob_write(&out, CHAR_RIGHT_PARENTHESIS);+ in_atomic = FALSE;+ }++ if (!no_starstar && pattern < pattern_end && *pattern == CHAR_ASTERISK)+ {+ after_separator = is_start || (pattern[-2] == separator);++ do pattern++; while (pattern < pattern_end &&+ *pattern == CHAR_ASTERISK);++ if (pattern >= pattern_end)+ {+ no_slash_z = TRUE;+ break;+ }++ after_starstar = TRUE;++ if (after_separator && escape != 0 && *pattern == escape &&+ pattern + 1 < pattern_end && pattern[1] == separator)+ pattern++;++ if (is_start)+ {+ if (*pattern != separator) continue;++ out.out_str[0] = CHAR_LEFT_PARENTHESIS;+ out.out_str[1] = CHAR_QUESTION_MARK;+ out.out_str[2] = CHAR_COLON;+ out.out_str[3] = CHAR_BACKSLASH;+ out.out_str[4] = CHAR_A;+ out.out_str[5] = CHAR_VERTICAL_LINE;+ convert_glob_write_str(&out, 6);++ convert_glob_print_separator(&out, separator, with_escape);+ convert_glob_write(&out, CHAR_RIGHT_PARENTHESIS);++ pattern++;+ continue;+ }++ convert_glob_print_commit(&out);++ if (!after_separator || *pattern != separator)+ {+ out.out_str[0] = CHAR_DOT;+ out.out_str[1] = CHAR_ASTERISK;+ out.out_str[2] = CHAR_QUESTION_MARK;+ convert_glob_write_str(&out, 3);+ continue;+ }++ out.out_str[0] = CHAR_LEFT_PARENTHESIS;+ out.out_str[1] = CHAR_QUESTION_MARK;+ out.out_str[2] = CHAR_COLON;+ out.out_str[3] = CHAR_DOT;+ out.out_str[4] = CHAR_ASTERISK;+ out.out_str[5] = CHAR_QUESTION_MARK;++ convert_glob_write_str(&out, 6);++ convert_glob_print_separator(&out, separator, with_escape);++ out.out_str[0] = CHAR_RIGHT_PARENTHESIS;+ out.out_str[1] = CHAR_QUESTION_MARK;+ out.out_str[2] = CHAR_QUESTION_MARK;+ convert_glob_write_str(&out, 3);++ pattern++;+ continue;+ }++ if (pattern < pattern_end && *pattern == CHAR_ASTERISK)+ {+ do pattern++; while (pattern < pattern_end &&+ *pattern == CHAR_ASTERISK);+ }++ if (no_wildsep)+ {+ if (pattern >= pattern_end)+ {+ no_slash_z = TRUE;+ break;+ }++ /* Start check must be after the end check. */+ if (is_start) continue;+ }++ if (!is_start)+ {+ if (after_starstar)+ {+ out.out_str[0] = CHAR_LEFT_PARENTHESIS;+ out.out_str[1] = CHAR_QUESTION_MARK;+ out.out_str[2] = CHAR_GREATER_THAN_SIGN;+ convert_glob_write_str(&out, 3);+ in_atomic = TRUE;+ }+ else+ convert_glob_print_commit(&out);+ }++ if (no_wildsep)+ convert_glob_write(&out, CHAR_DOT);+ else+ convert_glob_print_wildcard(&out, separator, with_escape);++ out.out_str[0] = CHAR_ASTERISK;+ out.out_str[1] = CHAR_QUESTION_MARK;+ if (pattern >= pattern_end)+ out.out_str[1] = CHAR_PLUS;+ convert_glob_write_str(&out, 2);+ continue;+ }++ if (c == CHAR_QUESTION_MARK)+ {+ if (no_wildsep)+ convert_glob_write(&out, CHAR_DOT);+ else+ convert_glob_print_wildcard(&out, separator, with_escape);+ continue;+ }++ if (c == CHAR_LEFT_SQUARE_BRACKET)+ {+ result = convert_glob_parse_range(&pattern, pattern_end,+ &out, utf, separator, with_escape, escape, no_wildsep);+ if (result != 0) break;+ continue;+ }++ if (escape != 0 && c == escape)+ {+ if (pattern >= pattern_end)+ {+ result = PCRE2_ERROR_CONVERT_SYNTAX;+ break;+ }+ c = *pattern++;+ }++ if (c < 128 && strchr(pcre2_escaped_literals, c) != NULL)+ convert_glob_write(&out, CHAR_BACKSLASH);++ convert_glob_write(&out, c);+ }++if (result == 0)+ {+ if (!no_slash_z)+ {+ out.out_str[0] = CHAR_BACKSLASH;+ out.out_str[1] = CHAR_z;+ convert_glob_write_str(&out, 2);+ }++ if (in_atomic)+ convert_glob_write(&out, CHAR_RIGHT_PARENTHESIS);++ convert_glob_write(&out, CHAR_NUL);++ if (!dummyrun && out.output_size != (PCRE2_SIZE) (out.output - use_buffer))+ result = PCRE2_ERROR_NOMEMORY;+ }++if (result != 0)+ {+ *bufflenptr = pattern - pattern_start;+ return result;+ }++*bufflenptr = out.output_size - 1;+return 0;+}+++/*************************************************+* Convert pattern *+*************************************************/++/* This is the external-facing function for converting other forms of pattern+into PCRE2 regular expression patterns. On error, the bufflenptr argument is+used to return an offset in the original pattern.++Arguments:+ pattern the input pattern+ plength length of input, or PCRE2_ZERO_TERMINATED+ options options bits+ buffptr pointer to pointer to output buffer+ bufflenptr pointer to length of output buffer+ ccontext convert context or NULL++Returns: 0 for success, else an error code (+ve or -ve)+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_pattern_convert(PCRE2_SPTR pattern, PCRE2_SIZE plength, uint32_t options,+ PCRE2_UCHAR **buffptr, PCRE2_SIZE *bufflenptr,+ pcre2_convert_context *ccontext)+{+int i, rc;+PCRE2_UCHAR dummy_buffer[DUMMY_BUFFER_SIZE];+PCRE2_UCHAR *use_buffer = dummy_buffer;+PCRE2_SIZE use_length = DUMMY_BUFFER_SIZE;+BOOL utf = (options & PCRE2_CONVERT_UTF) != 0;+uint32_t pattype = options & TYPE_OPTIONS;++if (pattern == NULL || bufflenptr == NULL) return PCRE2_ERROR_NULL;++if ((options & ~ALL_OPTIONS) != 0 || /* Undefined bit set */+ (pattype & (~pattype+1)) != pattype || /* More than one type set */+ pattype == 0) /* No type set */+ {+ *bufflenptr = 0; /* Error offset */+ return PCRE2_ERROR_BADOPTION;+ }++if (plength == PCRE2_ZERO_TERMINATED) plength = PRIV(strlen)(pattern);+if (ccontext == NULL) ccontext =+ (pcre2_convert_context *)(&PRIV(default_convert_context));++/* Check UTF if required. */++#ifndef SUPPORT_UNICODE+if (utf)+ {+ *bufflenptr = 0; /* Error offset */+ return PCRE2_ERROR_UNICODE_NOT_SUPPORTED;+ }+#else+if (utf && (options & PCRE2_CONVERT_NO_UTF_CHECK) == 0)+ {+ PCRE2_SIZE erroroffset;+ rc = PRIV(valid_utf)(pattern, plength, &erroroffset);+ if (rc != 0)+ {+ *bufflenptr = erroroffset;+ return rc;+ }+ }+#endif++/* If buffptr is not NULL, and what it points to is not NULL, we are being+provided with a buffer and a length, so set them as the buffer to use. */++if (buffptr != NULL && *buffptr != NULL)+ {+ use_buffer = *buffptr;+ use_length = *bufflenptr;+ }++/* Call an individual converter, either just once (if a buffer was provided or+just the length is needed), or twice (if a memory allocation is required). */++for (i = 0; i < 2; i++)+ {+ PCRE2_UCHAR *allocated;+ BOOL dummyrun = buffptr == NULL || *buffptr == NULL;++ switch(pattype)+ {+ case PCRE2_CONVERT_GLOB:+ rc = convert_glob(options & ~PCRE2_CONVERT_GLOB, pattern, plength, utf,+ use_buffer, use_length, bufflenptr, dummyrun, ccontext);+ break;++ case PCRE2_CONVERT_POSIX_BASIC:+ case PCRE2_CONVERT_POSIX_EXTENDED:+ rc = convert_posix(pattype, pattern, plength, utf, use_buffer, use_length,+ bufflenptr, dummyrun, ccontext);+ break;++ default:+ *bufflenptr = 0; /* Error offset */+ return PCRE2_ERROR_INTERNAL;+ }++ if (rc != 0 || /* Error */+ buffptr == NULL || /* Just the length is required */+ *buffptr != NULL) /* Buffer was provided or allocated */+ return rc;++ /* Allocate memory for the buffer, with hidden space for an allocator at+ the start. The next time round the loop runs the conversion for real. */++ allocated = PRIV(memctl_malloc)(sizeof(pcre2_memctl) ++ (*bufflenptr + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)ccontext);+ if (allocated == NULL) return PCRE2_ERROR_NOMEMORY;+ *buffptr = (PCRE2_UCHAR *)(((char *)allocated) + sizeof(pcre2_memctl));++ use_buffer = *buffptr;+ use_length = *bufflenptr + 1;+ }++/* Control should never get here. */++return PCRE2_ERROR_INTERNAL;+}+++/*************************************************+* Free converted pattern *+*************************************************/++/* This frees a converted pattern that was put in newly-allocated memory.++Argument: the converted pattern+Returns: nothing+*/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_converted_pattern_free(PCRE2_UCHAR *converted)+{+if (converted != NULL)+ {+ pcre2_memctl *memctl =+ (pcre2_memctl *)((char *)converted - sizeof(pcre2_memctl));+ memctl->free(memctl, memctl->memory_data);+ }+}++/* End of pcre2_convert.c */
+ src/c/pcre2/src/pcre2_dfa_match.c view
@@ -0,0 +1,3982 @@+/*************************************************+* 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) 2016-2020 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.+-----------------------------------------------------------------------------+*/+++/* This module contains the external function pcre2_dfa_match(), which is an+alternative matching function that uses a sort of DFA algorithm (not a true+FSM). This is NOT Perl-compatible, but it has advantages in certain+applications. */+++/* NOTE ABOUT PERFORMANCE: A user of this function sent some code that improved+the performance of his patterns greatly. I could not use it as it stood, as it+was not thread safe, and made assumptions about pattern sizes. Also, it caused+test 7 to loop, and test 9 to crash with a segfault.++The issue is the check for duplicate states, which is done by a simple linear+search up the state list. (Grep for "duplicate" below to find the code.) For+many patterns, there will never be many states active at one time, so a simple+linear search is fine. In patterns that have many active states, it might be a+bottleneck. The suggested code used an indexing scheme to remember which states+had previously been used for each character, and avoided the linear search when+it knew there was no chance of a duplicate. This was implemented when adding+states to the state lists.++I wrote some thread-safe, not-limited code to try something similar at the time+of checking for duplicates (instead of when adding states), using index vectors+on the stack. It did give a 13% improvement with one specially constructed+pattern for certain subject strings, but on other strings and on many of the+simpler patterns in the test suite it did worse. The major problem, I think,+was the extra time to initialize the index. This had to be done for each call+of internal_dfa_match(). (The supplied patch used a static vector, initialized+only once - I suspect this was the cause of the problems with the tests.)++Overall, I concluded that the gains in some cases did not outweigh the losses+in others, so I abandoned this code. */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#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 PUBLIC_DFA_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_DFA_SHORTEST|PCRE2_DFA_RESTART| \+ PCRE2_COPY_MATCHED_SUBJECT)+++/*************************************************+* Code parameters and static tables *+*************************************************/++/* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes+into others, under special conditions. A gap of 20 between the blocks should be+enough. The resulting opcodes don't have to be less than 256 because they are+never stored, so we push them well clear of the normal opcodes. */++#define OP_PROP_EXTRA 300+#define OP_EXTUNI_EXTRA 320+#define OP_ANYNL_EXTRA 340+#define OP_HSPACE_EXTRA 360+#define OP_VSPACE_EXTRA 380+++/* This table identifies those opcodes that are followed immediately by a+character that is to be tested in some way. This makes it possible to+centralize the loading of these characters. In the case of Type * etc, the+"character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a+small value. Non-zero values in the table are the offsets from the opcode where+the character is to be found. ***NOTE*** If the start of this table is+modified, the three tables that follow must also be modified. */++static const uint8_t coptable[] = {+ 0, /* End */+ 0, 0, 0, 0, 0, /* \A, \G, \K, \B, \b */+ 0, 0, 0, 0, 0, 0, /* \D, \d, \S, \s, \W, \w */+ 0, 0, 0, /* Any, AllAny, Anybyte */+ 0, 0, /* \P, \p */+ 0, 0, 0, 0, 0, /* \R, \H, \h, \V, \v */+ 0, /* \X */+ 0, 0, 0, 0, 0, 0, /* \Z, \z, $, $M, ^, ^M */+ 1, /* Char */+ 1, /* Chari */+ 1, /* not */+ 1, /* noti */+ /* Positive single-char repeats */+ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */+ 1+IMM2_SIZE, 1+IMM2_SIZE, /* upto, minupto */+ 1+IMM2_SIZE, /* exact */+ 1, 1, 1, 1+IMM2_SIZE, /* *+, ++, ?+, upto+ */+ 1, 1, 1, 1, 1, 1, /* *I, *?I, +I, +?I, ?I, ??I */+ 1+IMM2_SIZE, 1+IMM2_SIZE, /* upto I, minupto I */+ 1+IMM2_SIZE, /* exact I */+ 1, 1, 1, 1+IMM2_SIZE, /* *+I, ++I, ?+I, upto+I */+ /* Negative single-char repeats - only for chars < 256 */+ 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */+ 1+IMM2_SIZE, 1+IMM2_SIZE, /* NOT upto, minupto */+ 1+IMM2_SIZE, /* NOT exact */+ 1, 1, 1, 1+IMM2_SIZE, /* NOT *+, ++, ?+, upto+ */+ 1, 1, 1, 1, 1, 1, /* NOT *I, *?I, +I, +?I, ?I, ??I */+ 1+IMM2_SIZE, 1+IMM2_SIZE, /* NOT upto I, minupto I */+ 1+IMM2_SIZE, /* NOT exact I */+ 1, 1, 1, 1+IMM2_SIZE, /* NOT *+I, ++I, ?+I, upto+I */+ /* Positive type repeats */+ 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */+ 1+IMM2_SIZE, 1+IMM2_SIZE, /* Type upto, minupto */+ 1+IMM2_SIZE, /* Type exact */+ 1, 1, 1, 1+IMM2_SIZE, /* Type *+, ++, ?+, upto+ */+ /* Character class & ref repeats */+ 0, 0, 0, 0, 0, 0, /* *, *?, +, +?, ?, ?? */+ 0, 0, /* CRRANGE, CRMINRANGE */+ 0, 0, 0, 0, /* Possessive *+, ++, ?+, CRPOSRANGE */+ 0, /* CLASS */+ 0, /* NCLASS */+ 0, /* XCLASS - variable length */+ 0, /* REF */+ 0, /* REFI */+ 0, /* DNREF */+ 0, /* DNREFI */+ 0, /* RECURSE */+ 0, /* CALLOUT */+ 0, /* CALLOUT_STR */+ 0, /* Alt */+ 0, /* Ket */+ 0, /* KetRmax */+ 0, /* KetRmin */+ 0, /* KetRpos */+ 0, /* Reverse */+ 0, /* Assert */+ 0, /* Assert not */+ 0, /* Assert behind */+ 0, /* Assert behind not */+ 0, /* NA assert */+ 0, /* NA assert behind */+ 0, /* ONCE */+ 0, /* SCRIPT_RUN */+ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */+ 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */+ 0, 0, /* CREF, DNCREF */+ 0, 0, /* RREF, DNRREF */+ 0, 0, /* FALSE, TRUE */+ 0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */+ 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */+ 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */+ 0, 0, /* COMMIT, COMMIT_ARG */+ 0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */+ 0, 0, 0 /* CLOSE, SKIPZERO, DEFINE */+};++/* This table identifies those opcodes that inspect a character. It is used to+remember the fact that a character could have been inspected when the end of+the subject is reached. ***NOTE*** If the start of this table is modified, the+two tables that follow must also be modified. */++static const uint8_t poptable[] = {+ 0, /* End */+ 0, 0, 0, 1, 1, /* \A, \G, \K, \B, \b */+ 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */+ 1, 1, 1, /* Any, AllAny, Anybyte */+ 1, 1, /* \P, \p */+ 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */+ 1, /* \X */+ 0, 0, 0, 0, 0, 0, /* \Z, \z, $, $M, ^, ^M */+ 1, /* Char */+ 1, /* Chari */+ 1, /* not */+ 1, /* noti */+ /* Positive single-char repeats */+ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */+ 1, 1, 1, /* upto, minupto, exact */+ 1, 1, 1, 1, /* *+, ++, ?+, upto+ */+ 1, 1, 1, 1, 1, 1, /* *I, *?I, +I, +?I, ?I, ??I */+ 1, 1, 1, /* upto I, minupto I, exact I */+ 1, 1, 1, 1, /* *+I, ++I, ?+I, upto+I */+ /* Negative single-char repeats - only for chars < 256 */+ 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */+ 1, 1, 1, /* NOT upto, minupto, exact */+ 1, 1, 1, 1, /* NOT *+, ++, ?+, upto+ */+ 1, 1, 1, 1, 1, 1, /* NOT *I, *?I, +I, +?I, ?I, ??I */+ 1, 1, 1, /* NOT upto I, minupto I, exact I */+ 1, 1, 1, 1, /* NOT *+I, ++I, ?+I, upto+I */+ /* Positive type repeats */+ 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */+ 1, 1, 1, /* Type upto, minupto, exact */+ 1, 1, 1, 1, /* Type *+, ++, ?+, upto+ */+ /* Character class & ref repeats */+ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */+ 1, 1, /* CRRANGE, CRMINRANGE */+ 1, 1, 1, 1, /* Possessive *+, ++, ?+, CRPOSRANGE */+ 1, /* CLASS */+ 1, /* NCLASS */+ 1, /* XCLASS - variable length */+ 0, /* REF */+ 0, /* REFI */+ 0, /* DNREF */+ 0, /* DNREFI */+ 0, /* RECURSE */+ 0, /* CALLOUT */+ 0, /* CALLOUT_STR */+ 0, /* Alt */+ 0, /* Ket */+ 0, /* KetRmax */+ 0, /* KetRmin */+ 0, /* KetRpos */+ 0, /* Reverse */+ 0, /* Assert */+ 0, /* Assert not */+ 0, /* Assert behind */+ 0, /* Assert behind not */+ 0, /* NA assert */+ 0, /* NA assert behind */+ 0, /* ONCE */+ 0, /* SCRIPT_RUN */+ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */+ 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */+ 0, 0, /* CREF, DNCREF */+ 0, 0, /* RREF, DNRREF */+ 0, 0, /* FALSE, TRUE */+ 0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */+ 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */+ 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */+ 0, 0, /* COMMIT, COMMIT_ARG */+ 0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */+ 0, 0, 0 /* CLOSE, SKIPZERO, DEFINE */+};++/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,+and \w */++static const uint8_t toptable1[] = {+ 0, 0, 0, 0, 0, 0,+ ctype_digit, ctype_digit,+ ctype_space, ctype_space,+ ctype_word, ctype_word,+ 0, 0 /* OP_ANY, OP_ALLANY */+};++static const uint8_t toptable2[] = {+ 0, 0, 0, 0, 0, 0,+ ctype_digit, 0,+ ctype_space, 0,+ ctype_word, 0,+ 1, 1 /* OP_ANY, OP_ALLANY */+};+++/* Structure for holding data about a particular state, which is in effect the+current data for an active path through the match tree. It must consist+entirely of ints because the working vector we are passed, and which we put+these structures in, is a vector of ints. */++typedef struct stateblock {+ int offset; /* Offset to opcode (-ve has meaning) */+ int count; /* Count for repeats */+ int data; /* Some use extra data */+} stateblock;++#define INTS_PER_STATEBLOCK (int)(sizeof(stateblock)/sizeof(int))+++/* Before version 10.32 the recursive calls of internal_dfa_match() were passed+local working space and output vectors that were created on the stack. This has+caused issues for some patterns, especially in small-stack environments such as+Windows. A new scheme is now in use which sets up a vector on the stack, but if+this is too small, heap memory is used, up to the heap_limit. The main+parameters are all numbers of ints because the workspace is a vector of ints.++The size of the starting stack vector, DFA_START_RWS_SIZE, is in bytes, and is+defined in pcre2_internal.h so as to be available to pcre2test when it is+finding the minimum heap requirement for a match. */++#define OVEC_UNIT (sizeof(PCRE2_SIZE)/sizeof(int))++#define RWS_BASE_SIZE (DFA_START_RWS_SIZE/sizeof(int)) /* Stack vector */+#define RWS_RSIZE 1000 /* Work size for recursion */+#define RWS_OVEC_RSIZE (1000*OVEC_UNIT) /* Ovector for recursion */+#define RWS_OVEC_OSIZE (2*OVEC_UNIT) /* Ovector in other cases */++/* This structure is at the start of each workspace block. */++typedef struct RWS_anchor {+ struct RWS_anchor *next;+ uint32_t size; /* Number of ints */+ uint32_t free; /* Number of ints */+} RWS_anchor;++#define RWS_ANCHOR_SIZE (sizeof(RWS_anchor)/sizeof(int))++++/*************************************************+* Process a callout *+*************************************************/++/* This function is called to perform a callout.++Arguments:+ code current code pointer+ offsets points to current capture offsets+ current_subject start of current subject match+ ptr current position in subject+ mb the match block+ extracode extra code offset when called from condition+ lengthptr where to return the callout length++Returns: the return from the callout+*/++static int+do_callout(PCRE2_SPTR code, PCRE2_SIZE *offsets, PCRE2_SPTR current_subject,+ PCRE2_SPTR ptr, dfa_match_block *mb, PCRE2_SIZE extracode,+ PCRE2_SIZE *lengthptr)+{+pcre2_callout_block *cb = mb->cb;++*lengthptr = (code[extracode] == OP_CALLOUT)?+ (PCRE2_SIZE)PRIV(OP_lengths)[OP_CALLOUT] :+ (PCRE2_SIZE)GET(code, 1 + 2*LINK_SIZE + extracode);++if (mb->callout == NULL) return 0; /* No callout provided */++/* Fixed fields in the callout block are set once and for all at the start of+matching. */++cb->offset_vector = offsets;+cb->start_match = (PCRE2_SIZE)(current_subject - mb->start_subject);+cb->current_position = (PCRE2_SIZE)(ptr - mb->start_subject);+cb->pattern_position = GET(code, 1 + extracode);+cb->next_item_length = GET(code, 1 + LINK_SIZE + extracode);++if (code[extracode] == OP_CALLOUT)+ {+ cb->callout_number = code[1 + 2*LINK_SIZE + extracode];+ cb->callout_string_offset = 0;+ cb->callout_string = NULL;+ cb->callout_string_length = 0;+ }+else+ {+ cb->callout_number = 0;+ cb->callout_string_offset = GET(code, 1 + 3*LINK_SIZE + extracode);+ cb->callout_string = code + (1 + 4*LINK_SIZE + extracode) + 1;+ cb->callout_string_length = *lengthptr - (1 + 4*LINK_SIZE) - 2;+ }++return (mb->callout)(cb, mb->callout_data);+}++++/*************************************************+* Expand local workspace memory *+*************************************************/++/* This function is called when internal_dfa_match() is about to be called+recursively and there is insufficient working space left in the current+workspace block. If there's an existing next block, use it; otherwise get a new+block unless the heap limit is reached.++Arguments:+ rwsptr pointer to block pointer (updated)+ ovecsize space needed for an ovector+ mb the match block++Returns: 0 rwsptr has been updated+ !0 an error code+*/++static int+more_workspace(RWS_anchor **rwsptr, unsigned int ovecsize, dfa_match_block *mb)+{+RWS_anchor *rws = *rwsptr;+RWS_anchor *new;++if (rws->next != NULL)+ {+ new = rws->next;+ }++/* Sizes in the RWS_anchor blocks are in units of sizeof(int), but+mb->heap_limit and mb->heap_used are in kibibytes. Play carefully, to avoid+overflow. */++else+ {+ uint32_t newsize = (rws->size >= UINT32_MAX/2)? UINT32_MAX/2 : rws->size * 2;+ uint32_t newsizeK = newsize/(1024/sizeof(int));++ if (newsizeK + mb->heap_used > mb->heap_limit)+ newsizeK = (uint32_t)(mb->heap_limit - mb->heap_used);+ newsize = newsizeK*(1024/sizeof(int));++ if (newsize < RWS_RSIZE + ovecsize + RWS_ANCHOR_SIZE)+ return PCRE2_ERROR_HEAPLIMIT;+ new = mb->memctl.malloc(newsize*sizeof(int), mb->memctl.memory_data);+ if (new == NULL) return PCRE2_ERROR_NOMEMORY;+ mb->heap_used += newsizeK;+ new->next = NULL;+ new->size = newsize;+ rws->next = new;+ }++new->free = new->size - RWS_ANCHOR_SIZE;+*rwsptr = new;+return 0;+}++++/*************************************************+* Match a Regular Expression - DFA engine *+*************************************************/++/* This internal function applies a compiled pattern to a subject string,+starting at a given point, using a DFA engine. This function is called from the+external one, possibly multiple times if the pattern is not anchored. The+function calls itself recursively for some kinds of subpattern.++Arguments:+ mb the match_data block with fixed information+ this_start_code the opening bracket of this subexpression's code+ current_subject where we currently are in the subject string+ start_offset start offset in the subject string+ offsets vector to contain the matching string offsets+ offsetcount size of same+ workspace vector of workspace+ wscount size of same+ rlevel function call recursion level++Returns: > 0 => number of match offset pairs placed in offsets+ = 0 => offsets overflowed; longest matches are present+ -1 => failed to match+ < -1 => some kind of unexpected problem++The following macros are used for adding states to the two state vectors (one+for the current character, one for the following character). */++#define ADD_ACTIVE(x,y) \+ if (active_count++ < wscount) \+ { \+ next_active_state->offset = (x); \+ next_active_state->count = (y); \+ next_active_state++; \+ } \+ else return PCRE2_ERROR_DFA_WSSIZE++#define ADD_ACTIVE_DATA(x,y,z) \+ if (active_count++ < wscount) \+ { \+ next_active_state->offset = (x); \+ next_active_state->count = (y); \+ next_active_state->data = (z); \+ next_active_state++; \+ } \+ else return PCRE2_ERROR_DFA_WSSIZE++#define ADD_NEW(x,y) \+ if (new_count++ < wscount) \+ { \+ next_new_state->offset = (x); \+ next_new_state->count = (y); \+ next_new_state++; \+ } \+ else return PCRE2_ERROR_DFA_WSSIZE++#define ADD_NEW_DATA(x,y,z) \+ if (new_count++ < wscount) \+ { \+ next_new_state->offset = (x); \+ next_new_state->count = (y); \+ next_new_state->data = (z); \+ next_new_state++; \+ } \+ else return PCRE2_ERROR_DFA_WSSIZE++/* And now, here is the code */++static int+internal_dfa_match(+ dfa_match_block *mb,+ PCRE2_SPTR this_start_code,+ PCRE2_SPTR current_subject,+ PCRE2_SIZE start_offset,+ PCRE2_SIZE *offsets,+ uint32_t offsetcount,+ int *workspace,+ int wscount,+ uint32_t rlevel,+ int *RWS)+{+stateblock *active_states, *new_states, *temp_states;+stateblock *next_active_state, *next_new_state;+const uint8_t *ctypes, *lcc, *fcc;+PCRE2_SPTR ptr;+PCRE2_SPTR end_code;+dfa_recursion_info new_recursive;+int active_count, new_count, match_count;++/* Some fields in the mb block are frequently referenced, so we load them into+independent variables in the hope that this will perform better. */++PCRE2_SPTR start_subject = mb->start_subject;+PCRE2_SPTR end_subject = mb->end_subject;+PCRE2_SPTR start_code = mb->start_code;++#ifdef SUPPORT_UNICODE+BOOL utf = (mb->poptions & PCRE2_UTF) != 0;+BOOL utf_or_ucp = utf || (mb->poptions & PCRE2_UCP) != 0;+#else+BOOL utf = FALSE;+#endif++BOOL reset_could_continue = FALSE;++if (mb->match_call_count++ >= mb->match_limit) return PCRE2_ERROR_MATCHLIMIT;+if (rlevel++ > mb->match_limit_depth) return PCRE2_ERROR_DEPTHLIMIT;+offsetcount &= (uint32_t)(-2); /* Round down */++wscount -= 2;+wscount = (wscount - (wscount % (INTS_PER_STATEBLOCK * 2))) /+ (2 * INTS_PER_STATEBLOCK);++ctypes = mb->tables + ctypes_offset;+lcc = mb->tables + lcc_offset;+fcc = mb->tables + fcc_offset;++match_count = PCRE2_ERROR_NOMATCH; /* A negative number */++active_states = (stateblock *)(workspace + 2);+next_new_state = new_states = active_states + wscount;+new_count = 0;++/* The first thing in any (sub) pattern is a bracket of some sort. Push all+the alternative states onto the list, and find out where the end is. This+makes is possible to use this function recursively, when we want to stop at a+matching internal ket rather than at the end.++If we are dealing with a backward assertion we have to find out the maximum+amount to move back, and set up each alternative appropriately. */++if (*this_start_code == OP_ASSERTBACK || *this_start_code == OP_ASSERTBACK_NOT)+ {+ size_t max_back = 0;+ size_t gone_back;++ end_code = this_start_code;+ do+ {+ size_t back = (size_t)GET(end_code, 2+LINK_SIZE);+ if (back > max_back) max_back = back;+ end_code += GET(end_code, 1);+ }+ while (*end_code == OP_ALT);++ /* If we can't go back the amount required for the longest lookbehind+ pattern, go back as far as we can; some alternatives may still be viable. */++#ifdef SUPPORT_UNICODE+ /* In character mode we have to step back character by character */++ if (utf)+ {+ for (gone_back = 0; gone_back < max_back; gone_back++)+ {+ if (current_subject <= start_subject) break;+ current_subject--;+ ACROSSCHAR(current_subject > start_subject, current_subject,+ current_subject--);+ }+ }+ else+#endif++ /* In byte-mode we can do this quickly. */++ {+ size_t current_offset = (size_t)(current_subject - start_subject);+ gone_back = (current_offset < max_back)? current_offset : max_back;+ current_subject -= gone_back;+ }++ /* Save the earliest consulted character */++ if (current_subject < mb->start_used_ptr)+ mb->start_used_ptr = current_subject;++ /* Now we can process the individual branches. There will be an OP_REVERSE at+ the start of each branch, except when the length of the branch is zero. */++ end_code = this_start_code;+ do+ {+ uint32_t revlen = (end_code[1+LINK_SIZE] == OP_REVERSE)? 1 + LINK_SIZE : 0;+ size_t back = (revlen == 0)? 0 : (size_t)GET(end_code, 2+LINK_SIZE);+ if (back <= gone_back)+ {+ int bstate = (int)(end_code - start_code + 1 + LINK_SIZE + revlen);+ ADD_NEW_DATA(-bstate, 0, (int)(gone_back - back));+ }+ end_code += GET(end_code, 1);+ }+ while (*end_code == OP_ALT);+ }++/* This is the code for a "normal" subpattern (not a backward assertion). The+start of a whole pattern is always one of these. If we are at the top level,+we may be asked to restart matching from the same point that we reached for a+previous partial match. We still have to scan through the top-level branches to+find the end state. */++else+ {+ end_code = this_start_code;++ /* Restarting */++ if (rlevel == 1 && (mb->moptions & PCRE2_DFA_RESTART) != 0)+ {+ do { end_code += GET(end_code, 1); } while (*end_code == OP_ALT);+ new_count = workspace[1];+ if (!workspace[0])+ memcpy(new_states, active_states, (size_t)new_count * sizeof(stateblock));+ }++ /* Not restarting */++ else+ {+ int length = 1 + LINK_SIZE ++ ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||+ *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)+ ? IMM2_SIZE:0);+ do+ {+ ADD_NEW((int)(end_code - start_code + length), 0);+ end_code += GET(end_code, 1);+ length = 1 + LINK_SIZE;+ }+ while (*end_code == OP_ALT);+ }+ }++workspace[0] = 0; /* Bit indicating which vector is current */++/* Loop for scanning the subject */++ptr = current_subject;+for (;;)+ {+ int i, j;+ int clen, dlen;+ uint32_t c, d;+ int forced_fail = 0;+ BOOL partial_newline = FALSE;+ BOOL could_continue = reset_could_continue;+ reset_could_continue = FALSE;++ if (ptr > mb->last_used_ptr) mb->last_used_ptr = ptr;++ /* Make the new state list into the active state list and empty the+ new state list. */++ temp_states = active_states;+ active_states = new_states;+ new_states = temp_states;+ active_count = new_count;+ new_count = 0;++ workspace[0] ^= 1; /* Remember for the restarting feature */+ workspace[1] = active_count;++ /* Set the pointers for adding new states */++ next_active_state = active_states + active_count;+ next_new_state = new_states;++ /* Load the current character from the subject outside the loop, as many+ different states may want to look at it, and we assume that at least one+ will. */++ if (ptr < end_subject)+ {+ clen = 1; /* Number of data items in the character */+#ifdef SUPPORT_UNICODE+ GETCHARLENTEST(c, ptr, clen);+#else+ c = *ptr;+#endif /* SUPPORT_UNICODE */+ }+ else+ {+ clen = 0; /* This indicates the end of the subject */+ c = NOTACHAR; /* This value should never actually be used */+ }++ /* Scan up the active states and act on each one. The result of an action+ may be to add more states to the currently active list (e.g. on hitting a+ parenthesis) or it may be to put states on the new list, for considering+ when we move the character pointer on. */++ for (i = 0; i < active_count; i++)+ {+ stateblock *current_state = active_states + i;+ BOOL caseless = FALSE;+ PCRE2_SPTR code;+ uint32_t codevalue;+ int state_offset = current_state->offset;+ int rrc;+ int count;++ /* A negative offset is a special case meaning "hold off going to this+ (negated) state until the number of characters in the data field have+ been skipped". If the could_continue flag was passed over from a previous+ state, arrange for it to passed on. */++ if (state_offset < 0)+ {+ if (current_state->data > 0)+ {+ ADD_NEW_DATA(state_offset, current_state->count,+ current_state->data - 1);+ if (could_continue) reset_could_continue = TRUE;+ continue;+ }+ else+ {+ current_state->offset = state_offset = -state_offset;+ }+ }++ /* Check for a duplicate state with the same count, and skip if found.+ See the note at the head of this module about the possibility of improving+ performance here. */++ for (j = 0; j < i; j++)+ {+ if (active_states[j].offset == state_offset &&+ active_states[j].count == current_state->count)+ goto NEXT_ACTIVE_STATE;+ }++ /* The state offset is the offset to the opcode */++ code = start_code + state_offset;+ codevalue = *code;++ /* If this opcode inspects a character, but we are at the end of the+ subject, remember the fact for use when testing for a partial match. */++ if (clen == 0 && poptable[codevalue] != 0)+ could_continue = TRUE;++ /* If this opcode is followed by an inline character, load it. It is+ tempting to test for the presence of a subject character here, but that+ is wrong, because sometimes zero repetitions of the subject are+ permitted.++ We also use this mechanism for opcodes such as OP_TYPEPLUS that take an+ argument that is not a data character - but is always one byte long because+ the values are small. We have to take special action to deal with \P, \p,+ \H, \h, \V, \v and \X in this case. To keep the other cases fast, convert+ these ones to new opcodes. */++ if (coptable[codevalue] > 0)+ {+ dlen = 1;+#ifdef SUPPORT_UNICODE+ if (utf) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else+#endif /* SUPPORT_UNICODE */+ d = code[coptable[codevalue]];+ if (codevalue >= OP_TYPESTAR)+ {+ switch(d)+ {+ case OP_ANYBYTE: return PCRE2_ERROR_DFA_UITEM;+ case OP_NOTPROP:+ case OP_PROP: codevalue += OP_PROP_EXTRA; break;+ case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break;+ case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break;+ case OP_NOT_HSPACE:+ case OP_HSPACE: codevalue += OP_HSPACE_EXTRA; break;+ case OP_NOT_VSPACE:+ case OP_VSPACE: codevalue += OP_VSPACE_EXTRA; break;+ default: break;+ }+ }+ }+ else+ {+ dlen = 0; /* Not strictly necessary, but compilers moan */+ d = NOTACHAR; /* if these variables are not set. */+ }+++ /* Now process the individual opcodes */++ switch (codevalue)+ {+/* ========================================================================== */+ /* These cases are never obeyed. This is a fudge that causes a compile-+ time error if the vectors coptable or poptable, which are indexed by+ opcode, are not the correct length. It seems to be the only way to do+ such a check at compile time, as the sizeof() operator does not work+ in the C preprocessor. */++ case OP_TABLE_LENGTH:+ case OP_TABLE_LENGTH ++ ((sizeof(coptable) == OP_TABLE_LENGTH) &&+ (sizeof(poptable) == OP_TABLE_LENGTH)):+ return 0;++/* ========================================================================== */+ /* Reached a closing bracket. If not at the end of the pattern, carry+ on with the next opcode. For repeating opcodes, also add the repeat+ state. Note that KETRPOS will always be encountered at the end of the+ subpattern, because the possessive subpattern repeats are always handled+ using recursive calls. Thus, it never adds any new states.++ At the end of the (sub)pattern, unless we have an empty string and+ PCRE2_NOTEMPTY is set, or PCRE2_NOTEMPTY_ATSTART is set and we are at the+ start of the subject, save the match data, shifting up all previous+ matches so we always have the longest first. */++ case OP_KET:+ case OP_KETRMIN:+ case OP_KETRMAX:+ case OP_KETRPOS:+ if (code != end_code)+ {+ ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0);+ if (codevalue != OP_KET)+ {+ ADD_ACTIVE(state_offset - (int)GET(code, 1), 0);+ }+ }+ else+ {+ if (ptr > current_subject ||+ ((mb->moptions & PCRE2_NOTEMPTY) == 0 &&+ ((mb->moptions & PCRE2_NOTEMPTY_ATSTART) == 0 ||+ current_subject > start_subject + mb->start_offset)))+ {+ if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;+ else if (match_count > 0 && ++match_count * 2 > (int)offsetcount)+ match_count = 0;+ count = ((match_count == 0)? (int)offsetcount : match_count * 2) - 2;+ if (count > 0) (void)memmove(offsets + 2, offsets,+ (size_t)count * sizeof(PCRE2_SIZE));+ if (offsetcount >= 2)+ {+ offsets[0] = (PCRE2_SIZE)(current_subject - start_subject);+ offsets[1] = (PCRE2_SIZE)(ptr - start_subject);+ }+ if ((mb->moptions & PCRE2_DFA_SHORTEST) != 0) return match_count;+ }+ }+ break;++/* ========================================================================== */+ /* These opcodes add to the current list of states without looking+ at the current character. */++ /*-----------------------------------------------------------------*/+ case OP_ALT:+ do { code += GET(code, 1); } while (*code == OP_ALT);+ ADD_ACTIVE((int)(code - start_code), 0);+ break;++ /*-----------------------------------------------------------------*/+ case OP_BRA:+ case OP_SBRA:+ do+ {+ ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);+ code += GET(code, 1);+ }+ while (*code == OP_ALT);+ break;++ /*-----------------------------------------------------------------*/+ case OP_CBRA:+ case OP_SCBRA:+ ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE + IMM2_SIZE), 0);+ code += GET(code, 1);+ while (*code == OP_ALT)+ {+ ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);+ code += GET(code, 1);+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_BRAZERO:+ case OP_BRAMINZERO:+ ADD_ACTIVE(state_offset + 1, 0);+ code += 1 + GET(code, 2);+ while (*code == OP_ALT) code += GET(code, 1);+ ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);+ break;++ /*-----------------------------------------------------------------*/+ case OP_SKIPZERO:+ code += 1 + GET(code, 2);+ while (*code == OP_ALT) code += GET(code, 1);+ ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);+ break;++ /*-----------------------------------------------------------------*/+ case OP_CIRC:+ if (ptr == start_subject && (mb->moptions & PCRE2_NOTBOL) == 0)+ { ADD_ACTIVE(state_offset + 1, 0); }+ break;++ /*-----------------------------------------------------------------*/+ case OP_CIRCM:+ if ((ptr == start_subject && (mb->moptions & PCRE2_NOTBOL) == 0) ||+ ((ptr != end_subject || (mb->poptions & PCRE2_ALT_CIRCUMFLEX) != 0 )+ && WAS_NEWLINE(ptr)))+ { ADD_ACTIVE(state_offset + 1, 0); }+ break;++ /*-----------------------------------------------------------------*/+ case OP_EOD:+ if (ptr >= end_subject)+ {+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)+ return PCRE2_ERROR_PARTIAL;+ else { ADD_ACTIVE(state_offset + 1, 0); }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_SOD:+ if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); }+ break;++ /*-----------------------------------------------------------------*/+ case OP_SOM:+ if (ptr == start_subject + start_offset) { ADD_ACTIVE(state_offset + 1, 0); }+ break;+++/* ========================================================================== */+ /* These opcodes inspect the next subject character, and sometimes+ the previous one as well, but do not have an argument. The variable+ clen contains the length of the current character and is zero if we are+ at the end of the subject. */++ /*-----------------------------------------------------------------*/+ case OP_ANY:+ if (clen > 0 && !IS_NEWLINE(ptr))+ {+ if (ptr + 1 >= mb->end_subject &&+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&+ NLBLOCK->nltype == NLTYPE_FIXED &&+ NLBLOCK->nllen == 2 &&+ c == NLBLOCK->nl[0])+ {+ could_continue = partial_newline = TRUE;+ }+ else+ {+ ADD_NEW(state_offset + 1, 0);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_ALLANY:+ if (clen > 0)+ { ADD_NEW(state_offset + 1, 0); }+ break;++ /*-----------------------------------------------------------------*/+ case OP_EODN:+ if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - mb->nllen))+ {+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)+ return PCRE2_ERROR_PARTIAL;+ ADD_ACTIVE(state_offset + 1, 0);+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_DOLL:+ if ((mb->moptions & PCRE2_NOTEOL) == 0)+ {+ if (clen == 0 && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)+ could_continue = TRUE;+ else if (clen == 0 ||+ ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&+ (ptr == end_subject - mb->nllen)+ ))+ { ADD_ACTIVE(state_offset + 1, 0); }+ else if (ptr + 1 >= mb->end_subject &&+ (mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0 &&+ NLBLOCK->nltype == NLTYPE_FIXED &&+ NLBLOCK->nllen == 2 &&+ c == NLBLOCK->nl[0])+ {+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)+ {+ reset_could_continue = TRUE;+ ADD_NEW_DATA(-(state_offset + 1), 0, 1);+ }+ else could_continue = partial_newline = TRUE;+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_DOLLM:+ if ((mb->moptions & PCRE2_NOTEOL) == 0)+ {+ if (clen == 0 && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)+ could_continue = TRUE;+ else if (clen == 0 ||+ ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))+ { ADD_ACTIVE(state_offset + 1, 0); }+ else if (ptr + 1 >= mb->end_subject &&+ (mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0 &&+ NLBLOCK->nltype == NLTYPE_FIXED &&+ NLBLOCK->nllen == 2 &&+ c == NLBLOCK->nl[0])+ {+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)+ {+ reset_could_continue = TRUE;+ ADD_NEW_DATA(-(state_offset + 1), 0, 1);+ }+ else could_continue = partial_newline = TRUE;+ }+ }+ else if (IS_NEWLINE(ptr))+ { ADD_ACTIVE(state_offset + 1, 0); }+ break;++ /*-----------------------------------------------------------------*/++ case OP_DIGIT:+ case OP_WHITESPACE:+ case OP_WORDCHAR:+ if (clen > 0 && c < 256 &&+ ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0)+ { ADD_NEW(state_offset + 1, 0); }+ break;++ /*-----------------------------------------------------------------*/+ case OP_NOT_DIGIT:+ case OP_NOT_WHITESPACE:+ case OP_NOT_WORDCHAR:+ if (clen > 0 && (c >= 256 ||+ ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0))+ { ADD_NEW(state_offset + 1, 0); }+ break;++ /*-----------------------------------------------------------------*/+ case OP_WORD_BOUNDARY:+ case OP_NOT_WORD_BOUNDARY:+ {+ int left_word, right_word;++ if (ptr > start_subject)+ {+ PCRE2_SPTR temp = ptr - 1;+ if (temp < mb->start_used_ptr) mb->start_used_ptr = temp;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (utf) { BACKCHAR(temp); }+#endif+ GETCHARTEST(d, temp);+#ifdef SUPPORT_UNICODE+ if ((mb->poptions & PCRE2_UCP) != 0)+ {+ if (d == '_') left_word = TRUE; else+ {+ uint32_t cat = UCD_CATEGORY(d);+ left_word = (cat == ucp_L || cat == ucp_N);+ }+ }+ else+#endif+ left_word = d < 256 && (ctypes[d] & ctype_word) != 0;+ }+ else left_word = FALSE;++ if (clen > 0)+ {+ if (ptr >= mb->last_used_ptr)+ {+ PCRE2_SPTR temp = ptr + 1;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (utf) { FORWARDCHARTEST(temp, mb->end_subject); }+#endif+ mb->last_used_ptr = temp;+ }+#ifdef SUPPORT_UNICODE+ if ((mb->poptions & PCRE2_UCP) != 0)+ {+ if (c == '_') right_word = TRUE; else+ {+ uint32_t cat = UCD_CATEGORY(c);+ right_word = (cat == ucp_L || cat == ucp_N);+ }+ }+ else+#endif+ right_word = c < 256 && (ctypes[c] & ctype_word) != 0;+ }+ else right_word = FALSE;++ if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))+ { ADD_ACTIVE(state_offset + 1, 0); }+ }+ break;+++ /*-----------------------------------------------------------------*/+ /* 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.+ */++#ifdef SUPPORT_UNICODE+ case OP_PROP:+ case OP_NOTPROP:+ if (clen > 0)+ {+ BOOL OK;+ const uint32_t *cp;+ const ucd_record * prop = GET_UCD(c);+ switch(code[1])+ {+ case PT_ANY:+ OK = TRUE;+ break;++ case PT_LAMP:+ OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||+ prop->chartype == ucp_Lt;+ break;++ case PT_GC:+ OK = PRIV(ucp_gentype)[prop->chartype] == code[2];+ break;++ case PT_PC:+ OK = prop->chartype == code[2];+ break;++ case PT_SC:+ OK = prop->script == code[2];+ break;++ /* These are specials for combination cases. */++ case PT_ALNUM:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N;+ 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(c)+ {+ HSPACE_CASES:+ VSPACE_CASES:+ OK = TRUE;+ break;++ default:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z;+ break;+ }+ break;++ case PT_WORD:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||+ c == CHAR_UNDERSCORE;+ break;++ case PT_CLIST:+ cp = PRIV(ucd_caseless_sets) + code[2];+ for (;;)+ {+ if (c < *cp) { OK = FALSE; break; }+ if (c == *cp++) { OK = TRUE; break; }+ }+ break;++ case PT_UCNC:+ OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||+ c >= 0xe000;+ break;++ /* Should never occur, but keep compilers from grumbling. */++ default:+ OK = codevalue != OP_PROP;+ break;+ }++ if (OK == (codevalue == OP_PROP)) { ADD_NEW(state_offset + 3, 0); }+ }+ break;+#endif++++/* ========================================================================== */+ /* These opcodes likewise inspect the subject character, but have an+ argument that is not a data character. It is one of these opcodes:+ OP_ANY, OP_ALLANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE,+ OP_WORDCHAR, OP_NOT_WORDCHAR. The value is loaded into d. */++ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEPOSPLUS:+ count = current_state->count; /* Already matched */+ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }+ if (clen > 0)+ {+ if (d == OP_ANY && ptr + 1 >= mb->end_subject &&+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&+ NLBLOCK->nltype == NLTYPE_FIXED &&+ NLBLOCK->nllen == 2 &&+ c == NLBLOCK->nl[0])+ {+ could_continue = partial_newline = TRUE;+ }+ else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||+ (c < 256 &&+ (d != OP_ANY || !IS_NEWLINE(ptr)) &&+ ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))+ {+ if (count > 0 && codevalue == OP_TYPEPOSPLUS)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ count++;+ ADD_NEW(state_offset, count);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSQUERY:+ ADD_ACTIVE(state_offset + 2, 0);+ if (clen > 0)+ {+ if (d == OP_ANY && ptr + 1 >= mb->end_subject &&+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&+ NLBLOCK->nltype == NLTYPE_FIXED &&+ NLBLOCK->nllen == 2 &&+ c == NLBLOCK->nl[0])+ {+ could_continue = partial_newline = TRUE;+ }+ else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||+ (c < 256 &&+ (d != OP_ANY || !IS_NEWLINE(ptr)) &&+ ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))+ {+ if (codevalue == OP_TYPEPOSQUERY)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ ADD_NEW(state_offset + 2, 0);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPOSSTAR:+ ADD_ACTIVE(state_offset + 2, 0);+ if (clen > 0)+ {+ if (d == OP_ANY && ptr + 1 >= mb->end_subject &&+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&+ NLBLOCK->nltype == NLTYPE_FIXED &&+ NLBLOCK->nllen == 2 &&+ c == NLBLOCK->nl[0])+ {+ could_continue = partial_newline = TRUE;+ }+ else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||+ (c < 256 &&+ (d != OP_ANY || !IS_NEWLINE(ptr)) &&+ ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))+ {+ if (codevalue == OP_TYPEPOSSTAR)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ ADD_NEW(state_offset, 0);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_TYPEEXACT:+ count = current_state->count; /* Number already matched */+ if (clen > 0)+ {+ if (d == OP_ANY && ptr + 1 >= mb->end_subject &&+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&+ NLBLOCK->nltype == NLTYPE_FIXED &&+ NLBLOCK->nllen == 2 &&+ c == NLBLOCK->nl[0])+ {+ could_continue = partial_newline = TRUE;+ }+ else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||+ (c < 256 &&+ (d != OP_ANY || !IS_NEWLINE(ptr)) &&+ ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))+ {+ if (++count >= (int)GET2(code, 1))+ { ADD_NEW(state_offset + 1 + IMM2_SIZE + 1, 0); }+ else+ { ADD_NEW(state_offset, count); }+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEPOSUPTO:+ ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0);+ count = current_state->count; /* Number already matched */+ if (clen > 0)+ {+ if (d == OP_ANY && ptr + 1 >= mb->end_subject &&+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&+ NLBLOCK->nltype == NLTYPE_FIXED &&+ NLBLOCK->nllen == 2 &&+ c == NLBLOCK->nl[0])+ {+ could_continue = partial_newline = TRUE;+ }+ else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||+ (c < 256 &&+ (d != OP_ANY || !IS_NEWLINE(ptr)) &&+ ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))+ {+ if (codevalue == OP_TYPEPOSUPTO)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ if (++count >= (int)GET2(code, 1))+ { ADD_NEW(state_offset + 2 + IMM2_SIZE, 0); }+ else+ { ADD_NEW(state_offset, count); }+ }+ }+ break;++/* ========================================================================== */+ /* These are virtual opcodes that are used when something like+ OP_TYPEPLUS has OP_PROP, OP_NOTPROP, OP_ANYNL, or OP_EXTUNI as its+ argument. It keeps the code above fast for the other cases. The argument+ is in the d variable. */++#ifdef SUPPORT_UNICODE+ case OP_PROP_EXTRA + OP_TYPEPLUS:+ case OP_PROP_EXTRA + OP_TYPEMINPLUS:+ case OP_PROP_EXTRA + OP_TYPEPOSPLUS:+ count = current_state->count; /* Already matched */+ if (count > 0) { ADD_ACTIVE(state_offset + 4, 0); }+ if (clen > 0)+ {+ BOOL OK;+ const uint32_t *cp;+ const ucd_record * prop = GET_UCD(c);+ switch(code[2])+ {+ case PT_ANY:+ OK = TRUE;+ break;++ case PT_LAMP:+ OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||+ prop->chartype == ucp_Lt;+ break;++ case PT_GC:+ OK = PRIV(ucp_gentype)[prop->chartype] == code[3];+ break;++ case PT_PC:+ OK = prop->chartype == code[3];+ break;++ case PT_SC:+ OK = prop->script == code[3];+ break;++ /* These are specials for combination cases. */++ case PT_ALNUM:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N;+ 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(c)+ {+ HSPACE_CASES:+ VSPACE_CASES:+ OK = TRUE;+ break;++ default:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z;+ break;+ }+ break;++ case PT_WORD:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||+ c == CHAR_UNDERSCORE;+ break;++ case PT_CLIST:+ cp = PRIV(ucd_caseless_sets) + code[3];+ for (;;)+ {+ if (c < *cp) { OK = FALSE; break; }+ if (c == *cp++) { OK = TRUE; break; }+ }+ break;++ case PT_UCNC:+ OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||+ c >= 0xe000;+ break;++ /* Should never occur, but keep compilers from grumbling. */++ default:+ OK = codevalue != OP_PROP;+ break;+ }++ if (OK == (d == OP_PROP))+ {+ if (count > 0 && codevalue == OP_PROP_EXTRA + OP_TYPEPOSPLUS)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ count++;+ ADD_NEW(state_offset, count);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_EXTUNI_EXTRA + OP_TYPEPLUS:+ case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS:+ case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:+ count = current_state->count; /* Already matched */+ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }+ if (clen > 0)+ {+ int ncount = 0;+ if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ (void)PRIV(extuni)(c, ptr + clen, mb->start_subject, end_subject, utf,+ &ncount);+ count++;+ ADD_NEW_DATA(-state_offset, count, ncount);+ }+ break;+#endif++ /*-----------------------------------------------------------------*/+ case OP_ANYNL_EXTRA + OP_TYPEPLUS:+ case OP_ANYNL_EXTRA + OP_TYPEMINPLUS:+ case OP_ANYNL_EXTRA + OP_TYPEPOSPLUS:+ count = current_state->count; /* Already matched */+ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }+ if (clen > 0)+ {+ int ncount = 0;+ switch (c)+ {+ 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) break;+ goto ANYNL01;++ case CHAR_CR:+ if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;+ /* Fall through */++ ANYNL01:+ case CHAR_LF:+ if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ count++;+ ADD_NEW_DATA(-state_offset, count, ncount);+ break;++ default:+ break;+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_VSPACE_EXTRA + OP_TYPEPLUS:+ case OP_VSPACE_EXTRA + OP_TYPEMINPLUS:+ case OP_VSPACE_EXTRA + OP_TYPEPOSPLUS:+ count = current_state->count; /* Already matched */+ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }+ if (clen > 0)+ {+ BOOL OK;+ switch (c)+ {+ VSPACE_CASES:+ OK = TRUE;+ break;++ default:+ OK = FALSE;+ break;+ }++ if (OK == (d == OP_VSPACE))+ {+ if (count > 0 && codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSPLUS)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ count++;+ ADD_NEW_DATA(-state_offset, count, 0);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_HSPACE_EXTRA + OP_TYPEPLUS:+ case OP_HSPACE_EXTRA + OP_TYPEMINPLUS:+ case OP_HSPACE_EXTRA + OP_TYPEPOSPLUS:+ count = current_state->count; /* Already matched */+ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }+ if (clen > 0)+ {+ BOOL OK;+ switch (c)+ {+ HSPACE_CASES:+ OK = TRUE;+ break;++ default:+ OK = FALSE;+ break;+ }++ if (OK == (d == OP_HSPACE))+ {+ if (count > 0 && codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSPLUS)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ count++;+ ADD_NEW_DATA(-state_offset, count, 0);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+#ifdef SUPPORT_UNICODE+ case OP_PROP_EXTRA + OP_TYPEQUERY:+ case OP_PROP_EXTRA + OP_TYPEMINQUERY:+ case OP_PROP_EXTRA + OP_TYPEPOSQUERY:+ count = 4;+ goto QS1;++ case OP_PROP_EXTRA + OP_TYPESTAR:+ case OP_PROP_EXTRA + OP_TYPEMINSTAR:+ case OP_PROP_EXTRA + OP_TYPEPOSSTAR:+ count = 0;++ QS1:++ ADD_ACTIVE(state_offset + 4, 0);+ if (clen > 0)+ {+ BOOL OK;+ const uint32_t *cp;+ const ucd_record * prop = GET_UCD(c);+ switch(code[2])+ {+ case PT_ANY:+ OK = TRUE;+ break;++ case PT_LAMP:+ OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||+ prop->chartype == ucp_Lt;+ break;++ case PT_GC:+ OK = PRIV(ucp_gentype)[prop->chartype] == code[3];+ break;++ case PT_PC:+ OK = prop->chartype == code[3];+ break;++ case PT_SC:+ OK = prop->script == code[3];+ break;++ /* These are specials for combination cases. */++ case PT_ALNUM:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N;+ 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(c)+ {+ HSPACE_CASES:+ VSPACE_CASES:+ OK = TRUE;+ break;++ default:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z;+ break;+ }+ break;++ case PT_WORD:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||+ c == CHAR_UNDERSCORE;+ break;++ case PT_CLIST:+ cp = PRIV(ucd_caseless_sets) + code[3];+ for (;;)+ {+ if (c < *cp) { OK = FALSE; break; }+ if (c == *cp++) { OK = TRUE; break; }+ }+ break;++ case PT_UCNC:+ OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||+ c >= 0xe000;+ break;++ /* Should never occur, but keep compilers from grumbling. */++ default:+ OK = codevalue != OP_PROP;+ break;+ }++ if (OK == (d == OP_PROP))+ {+ if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSSTAR ||+ codevalue == OP_PROP_EXTRA + OP_TYPEPOSQUERY)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ ADD_NEW(state_offset + count, 0);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_EXTUNI_EXTRA + OP_TYPEQUERY:+ case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY:+ case OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY:+ count = 2;+ goto QS2;++ case OP_EXTUNI_EXTRA + OP_TYPESTAR:+ case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR:+ case OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR:+ count = 0;++ QS2:++ ADD_ACTIVE(state_offset + 2, 0);+ if (clen > 0)+ {+ int ncount = 0;+ if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||+ codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ (void)PRIV(extuni)(c, ptr + clen, mb->start_subject, end_subject, utf,+ &ncount);+ ADD_NEW_DATA(-(state_offset + count), 0, ncount);+ }+ break;+#endif++ /*-----------------------------------------------------------------*/+ case OP_ANYNL_EXTRA + OP_TYPEQUERY:+ case OP_ANYNL_EXTRA + OP_TYPEMINQUERY:+ case OP_ANYNL_EXTRA + OP_TYPEPOSQUERY:+ count = 2;+ goto QS3;++ case OP_ANYNL_EXTRA + OP_TYPESTAR:+ case OP_ANYNL_EXTRA + OP_TYPEMINSTAR:+ case OP_ANYNL_EXTRA + OP_TYPEPOSSTAR:+ count = 0;++ QS3:+ ADD_ACTIVE(state_offset + 2, 0);+ if (clen > 0)+ {+ int ncount = 0;+ switch (c)+ {+ 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) break;+ goto ANYNL02;++ case CHAR_CR:+ if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;+ /* Fall through */++ ANYNL02:+ case CHAR_LF:+ if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||+ codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ ADD_NEW_DATA(-(state_offset + (int)count), 0, ncount);+ break;++ default:+ break;+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_VSPACE_EXTRA + OP_TYPEQUERY:+ case OP_VSPACE_EXTRA + OP_TYPEMINQUERY:+ case OP_VSPACE_EXTRA + OP_TYPEPOSQUERY:+ count = 2;+ goto QS4;++ case OP_VSPACE_EXTRA + OP_TYPESTAR:+ case OP_VSPACE_EXTRA + OP_TYPEMINSTAR:+ case OP_VSPACE_EXTRA + OP_TYPEPOSSTAR:+ count = 0;++ QS4:+ ADD_ACTIVE(state_offset + 2, 0);+ if (clen > 0)+ {+ BOOL OK;+ switch (c)+ {+ VSPACE_CASES:+ OK = TRUE;+ break;++ default:+ OK = FALSE;+ break;+ }+ if (OK == (d == OP_VSPACE))+ {+ if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSSTAR ||+ codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSQUERY)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ ADD_NEW_DATA(-(state_offset + (int)count), 0, 0);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_HSPACE_EXTRA + OP_TYPEQUERY:+ case OP_HSPACE_EXTRA + OP_TYPEMINQUERY:+ case OP_HSPACE_EXTRA + OP_TYPEPOSQUERY:+ count = 2;+ goto QS5;++ case OP_HSPACE_EXTRA + OP_TYPESTAR:+ case OP_HSPACE_EXTRA + OP_TYPEMINSTAR:+ case OP_HSPACE_EXTRA + OP_TYPEPOSSTAR:+ count = 0;++ QS5:+ ADD_ACTIVE(state_offset + 2, 0);+ if (clen > 0)+ {+ BOOL OK;+ switch (c)+ {+ HSPACE_CASES:+ OK = TRUE;+ break;++ default:+ OK = FALSE;+ break;+ }++ if (OK == (d == OP_HSPACE))+ {+ if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSSTAR ||+ codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSQUERY)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ ADD_NEW_DATA(-(state_offset + (int)count), 0, 0);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+#ifdef SUPPORT_UNICODE+ case OP_PROP_EXTRA + OP_TYPEEXACT:+ case OP_PROP_EXTRA + OP_TYPEUPTO:+ case OP_PROP_EXTRA + OP_TYPEMINUPTO:+ case OP_PROP_EXTRA + OP_TYPEPOSUPTO:+ if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)+ { ADD_ACTIVE(state_offset + 1 + IMM2_SIZE + 3, 0); }+ count = current_state->count; /* Number already matched */+ if (clen > 0)+ {+ BOOL OK;+ const uint32_t *cp;+ const ucd_record * prop = GET_UCD(c);+ switch(code[1 + IMM2_SIZE + 1])+ {+ case PT_ANY:+ OK = TRUE;+ break;++ case PT_LAMP:+ OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||+ prop->chartype == ucp_Lt;+ break;++ case PT_GC:+ OK = PRIV(ucp_gentype)[prop->chartype] == code[1 + IMM2_SIZE + 2];+ break;++ case PT_PC:+ OK = prop->chartype == code[1 + IMM2_SIZE + 2];+ break;++ case PT_SC:+ OK = prop->script == code[1 + IMM2_SIZE + 2];+ break;++ /* These are specials for combination cases. */++ case PT_ALNUM:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N;+ 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(c)+ {+ HSPACE_CASES:+ VSPACE_CASES:+ OK = TRUE;+ break;++ default:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z;+ break;+ }+ break;++ case PT_WORD:+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||+ c == CHAR_UNDERSCORE;+ break;++ case PT_CLIST:+ cp = PRIV(ucd_caseless_sets) + code[1 + IMM2_SIZE + 2];+ for (;;)+ {+ if (c < *cp) { OK = FALSE; break; }+ if (c == *cp++) { OK = TRUE; break; }+ }+ break;++ case PT_UCNC:+ OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||+ c >= 0xe000;+ break;++ /* Should never occur, but keep compilers from grumbling. */++ default:+ OK = codevalue != OP_PROP;+ break;+ }++ if (OK == (d == OP_PROP))+ {+ if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSUPTO)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ if (++count >= (int)GET2(code, 1))+ { ADD_NEW(state_offset + 1 + IMM2_SIZE + 3, 0); }+ else+ { ADD_NEW(state_offset, count); }+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_EXTUNI_EXTRA + OP_TYPEEXACT:+ case OP_EXTUNI_EXTRA + OP_TYPEUPTO:+ case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:+ case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:+ if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)+ { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }+ count = current_state->count; /* Number already matched */+ if (clen > 0)+ {+ PCRE2_SPTR nptr;+ int ncount = 0;+ if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ nptr = PRIV(extuni)(c, ptr + clen, mb->start_subject, end_subject, utf,+ &ncount);+ if (nptr >= end_subject && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)+ reset_could_continue = TRUE;+ if (++count >= (int)GET2(code, 1))+ { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }+ else+ { ADD_NEW_DATA(-state_offset, count, ncount); }+ }+ break;+#endif++ /*-----------------------------------------------------------------*/+ case OP_ANYNL_EXTRA + OP_TYPEEXACT:+ case OP_ANYNL_EXTRA + OP_TYPEUPTO:+ case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:+ case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:+ if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)+ { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }+ count = current_state->count; /* Number already matched */+ if (clen > 0)+ {+ int ncount = 0;+ switch (c)+ {+ 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) break;+ goto ANYNL03;++ case CHAR_CR:+ if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;+ /* Fall through */++ ANYNL03:+ case CHAR_LF:+ if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ if (++count >= (int)GET2(code, 1))+ { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }+ else+ { ADD_NEW_DATA(-state_offset, count, ncount); }+ break;++ default:+ break;+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_VSPACE_EXTRA + OP_TYPEEXACT:+ case OP_VSPACE_EXTRA + OP_TYPEUPTO:+ case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:+ case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:+ if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)+ { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }+ count = current_state->count; /* Number already matched */+ if (clen > 0)+ {+ BOOL OK;+ switch (c)+ {+ VSPACE_CASES:+ OK = TRUE;+ break;++ default:+ OK = FALSE;+ }++ if (OK == (d == OP_VSPACE))+ {+ if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSUPTO)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ if (++count >= (int)GET2(code, 1))+ { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }+ else+ { ADD_NEW_DATA(-state_offset, count, 0); }+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_HSPACE_EXTRA + OP_TYPEEXACT:+ case OP_HSPACE_EXTRA + OP_TYPEUPTO:+ case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:+ case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:+ if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)+ { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }+ count = current_state->count; /* Number already matched */+ if (clen > 0)+ {+ BOOL OK;+ switch (c)+ {+ HSPACE_CASES:+ OK = TRUE;+ break;++ default:+ OK = FALSE;+ break;+ }++ if (OK == (d == OP_HSPACE))+ {+ if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSUPTO)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ if (++count >= (int)GET2(code, 1))+ { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }+ else+ { ADD_NEW_DATA(-state_offset, count, 0); }+ }+ }+ break;++/* ========================================================================== */+ /* These opcodes are followed by a character that is usually compared+ to the current subject character; it is loaded into d. We still get+ here even if there is no subject character, because in some cases zero+ repetitions are permitted. */++ /*-----------------------------------------------------------------*/+ case OP_CHAR:+ if (clen > 0 && c == d) { ADD_NEW(state_offset + dlen + 1, 0); }+ break;++ /*-----------------------------------------------------------------*/+ case OP_CHARI:+ if (clen == 0) break;++#ifdef SUPPORT_UNICODE+ if (utf_or_ucp)+ {+ if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else+ {+ unsigned int othercase;+ if (c < 128)+ othercase = fcc[c];+ else+ othercase = UCD_OTHERCASE(c);+ if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }+ }+ }+ else+#endif /* SUPPORT_UNICODE */+ /* Not UTF or UCP mode */+ {+ if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d))+ { ADD_NEW(state_offset + 2, 0); }+ }+ break;+++#ifdef SUPPORT_UNICODE+ /*-----------------------------------------------------------------*/+ /* This is a tricky one because it can match more than one character.+ Find out how many characters to skip, and then set up a negative state+ to wait for them to pass before continuing. */++ case OP_EXTUNI:+ if (clen > 0)+ {+ int ncount = 0;+ PCRE2_SPTR nptr = PRIV(extuni)(c, ptr + clen, mb->start_subject,+ end_subject, utf, &ncount);+ if (nptr >= end_subject && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)+ reset_could_continue = TRUE;+ ADD_NEW_DATA(-(state_offset + 1), 0, ncount);+ }+ break;+#endif++ /*-----------------------------------------------------------------*/+ /* This is a tricky like EXTUNI because it too can match more than one+ character (when CR is followed by LF). In this case, set up a negative+ state to wait for one character to pass before continuing. */++ case OP_ANYNL:+ if (clen > 0) switch(c)+ {+ 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) break;+ /* Fall through */++ case CHAR_LF:+ ADD_NEW(state_offset + 1, 0);+ break;++ case CHAR_CR:+ if (ptr + 1 >= end_subject)+ {+ ADD_NEW(state_offset + 1, 0);+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)+ reset_could_continue = TRUE;+ }+ else if (UCHAR21TEST(ptr + 1) == CHAR_LF)+ {+ ADD_NEW_DATA(-(state_offset + 1), 0, 1);+ }+ else+ {+ ADD_NEW(state_offset + 1, 0);+ }+ break;+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_NOT_VSPACE:+ if (clen > 0) switch(c)+ {+ VSPACE_CASES:+ break;++ default:+ ADD_NEW(state_offset + 1, 0);+ break;+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_VSPACE:+ if (clen > 0) switch(c)+ {+ VSPACE_CASES:+ ADD_NEW(state_offset + 1, 0);+ break;++ default:+ break;+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_NOT_HSPACE:+ if (clen > 0) switch(c)+ {+ HSPACE_CASES:+ break;++ default:+ ADD_NEW(state_offset + 1, 0);+ break;+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_HSPACE:+ if (clen > 0) switch(c)+ {+ HSPACE_CASES:+ ADD_NEW(state_offset + 1, 0);+ break;++ default:+ break;+ }+ break;++ /*-----------------------------------------------------------------*/+ /* Match a negated single character casefully. */++ case OP_NOT:+ if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); }+ break;++ /*-----------------------------------------------------------------*/+ /* Match a negated single character caselessly. */++ case OP_NOTI:+ if (clen > 0)+ {+ uint32_t otherd;+#ifdef SUPPORT_UNICODE+ if (utf_or_ucp && d >= 128)+ otherd = UCD_OTHERCASE(d);+ else+#endif /* SUPPORT_UNICODE */+ otherd = TABLE_GET(d, fcc, d);+ if (c != d && c != otherd)+ { ADD_NEW(state_offset + dlen + 1, 0); }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_POSPLUSI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTPOSPLUSI:+ caseless = TRUE;+ codevalue -= OP_STARI - OP_STAR;++ /* Fall through */+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_POSPLUS:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTPOSPLUS:+ count = current_state->count; /* Already matched */+ if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }+ if (clen > 0)+ {+ uint32_t otherd = NOTACHAR;+ if (caseless)+ {+#ifdef SUPPORT_UNICODE+ if (utf_or_ucp && d >= 128)+ otherd = UCD_OTHERCASE(d);+ else+#endif /* SUPPORT_UNICODE */+ otherd = TABLE_GET(d, fcc, d);+ }+ if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))+ {+ if (count > 0 &&+ (codevalue == OP_POSPLUS || codevalue == OP_NOTPOSPLUS))+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ count++;+ ADD_NEW(state_offset, count);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_POSQUERYI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTPOSQUERYI:+ caseless = TRUE;+ codevalue -= OP_STARI - OP_STAR;+ /* Fall through */+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_POSQUERY:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTPOSQUERY:+ ADD_ACTIVE(state_offset + dlen + 1, 0);+ if (clen > 0)+ {+ uint32_t otherd = NOTACHAR;+ if (caseless)+ {+#ifdef SUPPORT_UNICODE+ if (utf_or_ucp && d >= 128)+ otherd = UCD_OTHERCASE(d);+ else+#endif /* SUPPORT_UNICODE */+ otherd = TABLE_GET(d, fcc, d);+ }+ if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))+ {+ if (codevalue == OP_POSQUERY || codevalue == OP_NOTPOSQUERY)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ ADD_NEW(state_offset + dlen + 1, 0);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_STARI:+ case OP_MINSTARI:+ case OP_POSSTARI:+ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPOSSTARI:+ caseless = TRUE;+ codevalue -= OP_STARI - OP_STAR;+ /* Fall through */+ case OP_STAR:+ case OP_MINSTAR:+ case OP_POSSTAR:+ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPOSSTAR:+ ADD_ACTIVE(state_offset + dlen + 1, 0);+ if (clen > 0)+ {+ uint32_t otherd = NOTACHAR;+ if (caseless)+ {+#ifdef SUPPORT_UNICODE+ if (utf_or_ucp && d >= 128)+ otherd = UCD_OTHERCASE(d);+ else+#endif /* SUPPORT_UNICODE */+ otherd = TABLE_GET(d, fcc, d);+ }+ if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))+ {+ if (codevalue == OP_POSSTAR || codevalue == OP_NOTPOSSTAR)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ ADD_NEW(state_offset, 0);+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_EXACTI:+ case OP_NOTEXACTI:+ caseless = TRUE;+ codevalue -= OP_STARI - OP_STAR;+ /* Fall through */+ case OP_EXACT:+ case OP_NOTEXACT:+ count = current_state->count; /* Number already matched */+ if (clen > 0)+ {+ uint32_t otherd = NOTACHAR;+ if (caseless)+ {+#ifdef SUPPORT_UNICODE+ if (utf_or_ucp && d >= 128)+ otherd = UCD_OTHERCASE(d);+ else+#endif /* SUPPORT_UNICODE */+ otherd = TABLE_GET(d, fcc, d);+ }+ if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))+ {+ if (++count >= (int)GET2(code, 1))+ { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }+ else+ { ADD_NEW(state_offset, count); }+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_POSUPTOI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTPOSUPTOI:+ caseless = TRUE;+ codevalue -= OP_STARI - OP_STAR;+ /* Fall through */+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_POSUPTO:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTPOSUPTO:+ ADD_ACTIVE(state_offset + dlen + 1 + IMM2_SIZE, 0);+ count = current_state->count; /* Number already matched */+ if (clen > 0)+ {+ uint32_t otherd = NOTACHAR;+ if (caseless)+ {+#ifdef SUPPORT_UNICODE+ if (utf_or_ucp && d >= 128)+ otherd = UCD_OTHERCASE(d);+ else+#endif /* SUPPORT_UNICODE */+ otherd = TABLE_GET(d, fcc, d);+ }+ if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))+ {+ if (codevalue == OP_POSUPTO || codevalue == OP_NOTPOSUPTO)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ if (++count >= (int)GET2(code, 1))+ { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }+ else+ { ADD_NEW(state_offset, count); }+ }+ }+ break;+++/* ========================================================================== */+ /* These are the class-handling opcodes */++ case OP_CLASS:+ case OP_NCLASS:+ case OP_XCLASS:+ {+ BOOL isinclass = FALSE;+ int next_state_offset;+ PCRE2_SPTR ecode;++ /* For a simple class, there is always just a 32-byte table, and we+ can set isinclass from it. */++ if (codevalue != OP_XCLASS)+ {+ ecode = code + 1 + (32 / sizeof(PCRE2_UCHAR));+ if (clen > 0)+ {+ isinclass = (c > 255)? (codevalue == OP_NCLASS) :+ ((((uint8_t *)(code + 1))[c/8] & (1u << (c&7))) != 0);+ }+ }++ /* An extended class may have a table or a list of single characters,+ ranges, or both, and it may be positive or negative. There's a+ function that sorts all this out. */++ else+ {+ ecode = code + GET(code, 1);+ if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf);+ }++ /* At this point, isinclass is set for all kinds of class, and ecode+ points to the byte after the end of the class. If there is a+ quantifier, this is where it will be. */++ next_state_offset = (int)(ecode - start_code);++ switch (*ecode)+ {+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRPOSSTAR:+ ADD_ACTIVE(next_state_offset + 1, 0);+ if (isinclass)+ {+ if (*ecode == OP_CRPOSSTAR)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ ADD_NEW(state_offset, 0);+ }+ break;++ case OP_CRPLUS:+ case OP_CRMINPLUS:+ case OP_CRPOSPLUS:+ count = current_state->count; /* Already matched */+ if (count > 0) { ADD_ACTIVE(next_state_offset + 1, 0); }+ if (isinclass)+ {+ if (count > 0 && *ecode == OP_CRPOSPLUS)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ count++;+ ADD_NEW(state_offset, count);+ }+ break;++ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSQUERY:+ ADD_ACTIVE(next_state_offset + 1, 0);+ if (isinclass)+ {+ if (*ecode == OP_CRPOSQUERY)+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }+ ADD_NEW(next_state_offset + 1, 0);+ }+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ count = current_state->count; /* Already matched */+ if (count >= (int)GET2(ecode, 1))+ { ADD_ACTIVE(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }+ if (isinclass)+ {+ int max = (int)GET2(ecode, 1 + IMM2_SIZE);++ if (*ecode == OP_CRPOSRANGE && count >= (int)GET2(ecode, 1))+ {+ active_count--; /* Remove non-match possibility */+ next_active_state--;+ }++ if (++count >= max && max != 0) /* Max 0 => no limit */+ { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }+ else+ { ADD_NEW(state_offset, count); }+ }+ break;++ default:+ if (isinclass) { ADD_NEW(next_state_offset, 0); }+ break;+ }+ }+ break;++/* ========================================================================== */+ /* These are the opcodes for fancy brackets of various kinds. We have+ to use recursion in order to handle them. The "always failing" assertion+ (?!) is optimised to OP_FAIL when compiling, so we have to support that,+ though the other "backtracking verbs" are not supported. */++ case OP_FAIL:+ forced_fail++; /* Count FAILs for multiple states */+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ {+ int rc;+ int *local_workspace;+ PCRE2_SIZE *local_offsets;+ PCRE2_SPTR endasscode = code + GET(code, 1);+ RWS_anchor *rws = (RWS_anchor *)RWS;++ if (rws->free < RWS_RSIZE + RWS_OVEC_OSIZE)+ {+ rc = more_workspace(&rws, RWS_OVEC_OSIZE, mb);+ if (rc != 0) return rc;+ RWS = (int *)rws;+ }++ local_offsets = (PCRE2_SIZE *)(RWS + rws->size - rws->free);+ local_workspace = ((int *)local_offsets) + RWS_OVEC_OSIZE;+ rws->free -= RWS_RSIZE + RWS_OVEC_OSIZE;++ while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);++ rc = internal_dfa_match(+ mb, /* static match data */+ code, /* this subexpression's code */+ ptr, /* where we currently are */+ (PCRE2_SIZE)(ptr - start_subject), /* start offset */+ local_offsets, /* offset vector */+ RWS_OVEC_OSIZE/OVEC_UNIT, /* size of same */+ local_workspace, /* workspace vector */+ RWS_RSIZE, /* size of same */+ rlevel, /* function recursion level */+ RWS); /* recursion workspace */++ rws->free += RWS_RSIZE + RWS_OVEC_OSIZE;++ if (rc < 0 && rc != PCRE2_ERROR_NOMATCH) return rc;+ if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))+ { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_COND:+ case OP_SCOND:+ {+ int codelink = (int)GET(code, 1);+ PCRE2_UCHAR condcode;++ /* Because of the way auto-callout works during compile, a callout item+ is inserted between OP_COND and an assertion condition. This does not+ happen for the other conditions. */++ if (code[LINK_SIZE + 1] == OP_CALLOUT+ || code[LINK_SIZE + 1] == OP_CALLOUT_STR)+ {+ PCRE2_SIZE callout_length;+ rrc = do_callout(code, offsets, current_subject, ptr, mb,+ 1 + LINK_SIZE, &callout_length);+ if (rrc < 0) return rrc; /* Abandon */+ if (rrc > 0) break; /* Fail this thread */+ code += callout_length; /* Skip callout data */+ }++ condcode = code[LINK_SIZE+1];++ /* Back reference conditions and duplicate named recursion conditions+ are not supported */++ if (condcode == OP_CREF || condcode == OP_DNCREF ||+ condcode == OP_DNRREF)+ return PCRE2_ERROR_DFA_UCOND;++ /* The DEFINE condition is always false, and the assertion (?!) is+ converted to OP_FAIL. */++ if (condcode == OP_FALSE || condcode == OP_FAIL)+ { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }++ /* There is also an always-true condition */++ else if (condcode == OP_TRUE)+ { ADD_ACTIVE(state_offset + LINK_SIZE + 2, 0); }++ /* The only supported version of OP_RREF is for the value RREF_ANY,+ which means "test if in any recursion". We can't test for specifically+ recursed groups. */++ else if (condcode == OP_RREF)+ {+ unsigned int value = GET2(code, LINK_SIZE + 2);+ if (value != RREF_ANY) return PCRE2_ERROR_DFA_UCOND;+ if (mb->recursive != NULL)+ { ADD_ACTIVE(state_offset + LINK_SIZE + 2 + IMM2_SIZE, 0); }+ else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }+ }++ /* Otherwise, the condition is an assertion */++ else+ {+ int rc;+ int *local_workspace;+ PCRE2_SIZE *local_offsets;+ PCRE2_SPTR asscode = code + LINK_SIZE + 1;+ PCRE2_SPTR endasscode = asscode + GET(asscode, 1);+ RWS_anchor *rws = (RWS_anchor *)RWS;++ if (rws->free < RWS_RSIZE + RWS_OVEC_OSIZE)+ {+ rc = more_workspace(&rws, RWS_OVEC_OSIZE, mb);+ if (rc != 0) return rc;+ RWS = (int *)rws;+ }++ local_offsets = (PCRE2_SIZE *)(RWS + rws->size - rws->free);+ local_workspace = ((int *)local_offsets) + RWS_OVEC_OSIZE;+ rws->free -= RWS_RSIZE + RWS_OVEC_OSIZE;++ while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);++ rc = internal_dfa_match(+ mb, /* fixed match data */+ asscode, /* this subexpression's code */+ ptr, /* where we currently are */+ (PCRE2_SIZE)(ptr - start_subject), /* start offset */+ local_offsets, /* offset vector */+ RWS_OVEC_OSIZE/OVEC_UNIT, /* size of same */+ local_workspace, /* workspace vector */+ RWS_RSIZE, /* size of same */+ rlevel, /* function recursion level */+ RWS); /* recursion workspace */++ rws->free += RWS_RSIZE + RWS_OVEC_OSIZE;++ if (rc < 0 && rc != PCRE2_ERROR_NOMATCH) return rc;+ if ((rc >= 0) ==+ (condcode == OP_ASSERT || condcode == OP_ASSERTBACK))+ { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); }+ else+ { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_RECURSE:+ {+ int rc;+ int *local_workspace;+ PCRE2_SIZE *local_offsets;+ RWS_anchor *rws = (RWS_anchor *)RWS;+ dfa_recursion_info *ri;+ PCRE2_SPTR callpat = start_code + GET(code, 1);+ uint32_t recno = (callpat == mb->start_code)? 0 :+ GET2(callpat, 1 + LINK_SIZE);++ if (rws->free < RWS_RSIZE + RWS_OVEC_RSIZE)+ {+ rc = more_workspace(&rws, RWS_OVEC_RSIZE, mb);+ if (rc != 0) return rc;+ RWS = (int *)rws;+ }++ local_offsets = (PCRE2_SIZE *)(RWS + rws->size - rws->free);+ local_workspace = ((int *)local_offsets) + RWS_OVEC_RSIZE;+ rws->free -= RWS_RSIZE + RWS_OVEC_RSIZE;++ /* Check for repeating a recursion without advancing the subject+ pointer. This should catch convoluted mutual recursions. (Some simple+ cases are caught at compile time.) */++ for (ri = mb->recursive; ri != NULL; ri = ri->prevrec)+ if (recno == ri->group_num && ptr == ri->subject_position)+ return PCRE2_ERROR_RECURSELOOP;++ /* Remember this recursion and where we started it so as to+ catch infinite loops. */++ new_recursive.group_num = recno;+ new_recursive.subject_position = ptr;+ new_recursive.prevrec = mb->recursive;+ mb->recursive = &new_recursive;++ rc = internal_dfa_match(+ mb, /* fixed match data */+ callpat, /* this subexpression's code */+ ptr, /* where we currently are */+ (PCRE2_SIZE)(ptr - start_subject), /* start offset */+ local_offsets, /* offset vector */+ RWS_OVEC_RSIZE/OVEC_UNIT, /* size of same */+ local_workspace, /* workspace vector */+ RWS_RSIZE, /* size of same */+ rlevel, /* function recursion level */+ RWS); /* recursion workspace */++ rws->free += RWS_RSIZE + RWS_OVEC_RSIZE;+ mb->recursive = new_recursive.prevrec; /* Done this recursion */++ /* Ran out of internal offsets */++ if (rc == 0) return PCRE2_ERROR_DFA_RECURSE;++ /* For each successful matched substring, set up the next state with a+ count of characters to skip before trying it. Note that the count is in+ characters, not bytes. */++ if (rc > 0)+ {+ for (rc = rc*2 - 2; rc >= 0; rc -= 2)+ {+ PCRE2_SIZE charcount = local_offsets[rc+1] - local_offsets[rc];+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (utf)+ {+ PCRE2_SPTR p = start_subject + local_offsets[rc];+ PCRE2_SPTR pp = start_subject + local_offsets[rc+1];+ while (p < pp) if (NOT_FIRSTCU(*p++)) charcount--;+ }+#endif+ if (charcount > 0)+ {+ ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0,+ (int)(charcount - 1));+ }+ else+ {+ ADD_ACTIVE(state_offset + LINK_SIZE + 1, 0);+ }+ }+ }+ else if (rc != PCRE2_ERROR_NOMATCH) return rc;+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_BRAPOS:+ case OP_SBRAPOS:+ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ case OP_BRAPOSZERO:+ {+ int rc;+ int *local_workspace;+ PCRE2_SIZE *local_offsets;+ PCRE2_SIZE charcount, matched_count;+ PCRE2_SPTR local_ptr = ptr;+ RWS_anchor *rws = (RWS_anchor *)RWS;+ BOOL allow_zero;++ if (rws->free < RWS_RSIZE + RWS_OVEC_OSIZE)+ {+ rc = more_workspace(&rws, RWS_OVEC_OSIZE, mb);+ if (rc != 0) return rc;+ RWS = (int *)rws;+ }++ local_offsets = (PCRE2_SIZE *)(RWS + rws->size - rws->free);+ local_workspace = ((int *)local_offsets) + RWS_OVEC_OSIZE;+ rws->free -= RWS_RSIZE + RWS_OVEC_OSIZE;++ if (codevalue == OP_BRAPOSZERO)+ {+ allow_zero = TRUE;+ codevalue = *(++code); /* Codevalue will be one of above BRAs */+ }+ else allow_zero = FALSE;++ /* Loop to match the subpattern as many times as possible as if it were+ a complete pattern. */++ for (matched_count = 0;; matched_count++)+ {+ rc = internal_dfa_match(+ mb, /* fixed match data */+ code, /* this subexpression's code */+ local_ptr, /* where we currently are */+ (PCRE2_SIZE)(ptr - start_subject), /* start offset */+ local_offsets, /* offset vector */+ RWS_OVEC_OSIZE/OVEC_UNIT, /* size of same */+ local_workspace, /* workspace vector */+ RWS_RSIZE, /* size of same */+ rlevel, /* function recursion level */+ RWS); /* recursion workspace */++ /* Failed to match */++ if (rc < 0)+ {+ if (rc != PCRE2_ERROR_NOMATCH) return rc;+ break;+ }++ /* Matched: break the loop if zero characters matched. */++ charcount = local_offsets[1] - local_offsets[0];+ if (charcount == 0) break;+ local_ptr += charcount; /* Advance temporary position ptr */+ }++ rws->free += RWS_RSIZE + RWS_OVEC_OSIZE;++ /* At this point we have matched the subpattern matched_count+ times, and local_ptr is pointing to the character after the end of the+ last match. */++ if (matched_count > 0 || allow_zero)+ {+ PCRE2_SPTR end_subpattern = code;+ int next_state_offset;++ do { end_subpattern += GET(end_subpattern, 1); }+ while (*end_subpattern == OP_ALT);+ next_state_offset =+ (int)(end_subpattern - start_code + LINK_SIZE + 1);++ /* Optimization: if there are no more active states, and there+ are no new states yet set up, then skip over the subject string+ right here, to save looping. Otherwise, set up the new state to swing+ into action when the end of the matched substring is reached. */++ if (i + 1 >= active_count && new_count == 0)+ {+ ptr = local_ptr;+ clen = 0;+ ADD_NEW(next_state_offset, 0);+ }+ else+ {+ PCRE2_SPTR p = ptr;+ PCRE2_SPTR pp = local_ptr;+ charcount = (PCRE2_SIZE)(pp - p);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (utf) while (p < pp) if (NOT_FIRSTCU(*p++)) charcount--;+#endif+ ADD_NEW_DATA(-next_state_offset, 0, (int)(charcount - 1));+ }+ }+ }+ break;++ /*-----------------------------------------------------------------*/+ case OP_ONCE:+ {+ int rc;+ int *local_workspace;+ PCRE2_SIZE *local_offsets;+ RWS_anchor *rws = (RWS_anchor *)RWS;++ if (rws->free < RWS_RSIZE + RWS_OVEC_OSIZE)+ {+ rc = more_workspace(&rws, RWS_OVEC_OSIZE, mb);+ if (rc != 0) return rc;+ RWS = (int *)rws;+ }++ local_offsets = (PCRE2_SIZE *)(RWS + rws->size - rws->free);+ local_workspace = ((int *)local_offsets) + RWS_OVEC_OSIZE;+ rws->free -= RWS_RSIZE + RWS_OVEC_OSIZE;++ rc = internal_dfa_match(+ mb, /* fixed match data */+ code, /* this subexpression's code */+ ptr, /* where we currently are */+ (PCRE2_SIZE)(ptr - start_subject), /* start offset */+ local_offsets, /* offset vector */+ RWS_OVEC_OSIZE/OVEC_UNIT, /* size of same */+ local_workspace, /* workspace vector */+ RWS_RSIZE, /* size of same */+ rlevel, /* function recursion level */+ RWS); /* recursion workspace */++ rws->free += RWS_RSIZE + RWS_OVEC_OSIZE;++ if (rc >= 0)+ {+ PCRE2_SPTR end_subpattern = code;+ PCRE2_SIZE charcount = local_offsets[1] - local_offsets[0];+ int next_state_offset, repeat_state_offset;++ do { end_subpattern += GET(end_subpattern, 1); }+ while (*end_subpattern == OP_ALT);+ next_state_offset =+ (int)(end_subpattern - start_code + LINK_SIZE + 1);++ /* If the end of this subpattern is KETRMAX or KETRMIN, we must+ arrange for the repeat state also to be added to the relevant list.+ Calculate the offset, or set -1 for no repeat. */++ repeat_state_offset = (*end_subpattern == OP_KETRMAX ||+ *end_subpattern == OP_KETRMIN)?+ (int)(end_subpattern - start_code - GET(end_subpattern, 1)) : -1;++ /* If we have matched an empty string, add the next state at the+ current character pointer. This is important so that the duplicate+ checking kicks in, which is what breaks infinite loops that match an+ empty string. */++ if (charcount == 0)+ {+ ADD_ACTIVE(next_state_offset, 0);+ }++ /* Optimization: if there are no more active states, and there+ are no new states yet set up, then skip over the subject string+ right here, to save looping. Otherwise, set up the new state to swing+ into action when the end of the matched substring is reached. */++ else if (i + 1 >= active_count && new_count == 0)+ {+ ptr += charcount;+ clen = 0;+ ADD_NEW(next_state_offset, 0);++ /* If we are adding a repeat state at the new character position,+ we must fudge things so that it is the only current state.+ Otherwise, it might be a duplicate of one we processed before, and+ that would cause it to be skipped. */++ if (repeat_state_offset >= 0)+ {+ next_active_state = active_states;+ active_count = 0;+ i = -1;+ ADD_ACTIVE(repeat_state_offset, 0);+ }+ }+ else+ {+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (utf)+ {+ PCRE2_SPTR p = start_subject + local_offsets[0];+ PCRE2_SPTR pp = start_subject + local_offsets[1];+ while (p < pp) if (NOT_FIRSTCU(*p++)) charcount--;+ }+#endif+ ADD_NEW_DATA(-next_state_offset, 0, (int)(charcount - 1));+ if (repeat_state_offset >= 0)+ { ADD_NEW_DATA(-repeat_state_offset, 0, (int)(charcount - 1)); }+ }+ }+ else if (rc != PCRE2_ERROR_NOMATCH) return rc;+ }+ break;+++/* ========================================================================== */+ /* Handle callouts */++ case OP_CALLOUT:+ case OP_CALLOUT_STR:+ {+ PCRE2_SIZE callout_length;+ rrc = do_callout(code, offsets, current_subject, ptr, mb, 0,+ &callout_length);+ if (rrc < 0) return rrc; /* Abandon */+ if (rrc == 0)+ { ADD_ACTIVE(state_offset + (int)callout_length, 0); }+ }+ break;+++/* ========================================================================== */+ default: /* Unsupported opcode */+ return PCRE2_ERROR_DFA_UITEM;+ }++ NEXT_ACTIVE_STATE: continue;++ } /* End of loop scanning active states */++ /* We have finished the processing at the current subject character. If no+ new states have been set for the next character, we have found all the+ matches that we are going to find. If partial matching has been requested,+ check for appropriate conditions.++ The "forced_ fail" variable counts the number of (*F) encountered for the+ character. If it is equal to the original active_count (saved in+ workspace[1]) it means that (*F) was found on every active state. In this+ case we don't want to give a partial match.++ The "could_continue" variable is true if a state could have continued but+ for the fact that the end of the subject was reached. */++ if (new_count <= 0)+ {+ if (could_continue && /* Some could go on, and */+ forced_fail != workspace[1] && /* Not all forced fail & */+ ( /* either... */+ (mb->moptions & PCRE2_PARTIAL_HARD) != 0 /* Hard partial */+ || /* or... */+ ((mb->moptions & PCRE2_PARTIAL_SOFT) != 0 && /* Soft partial and */+ match_count < 0) /* no matches */+ ) && /* And... */+ (+ partial_newline || /* Either partial NL */+ ( /* or ... */+ ptr >= end_subject && /* End of subject and */+ ( /* either */+ ptr > mb->start_used_ptr || /* Inspected non-empty string */+ mb->allowemptypartial /* or pattern has lookbehind */+ ) /* or could match empty */+ )+ ))+ match_count = PCRE2_ERROR_PARTIAL;+ break; /* Exit from loop along the subject string */+ }++ /* One or more states are active for the next character. */++ ptr += clen; /* Advance to next subject character */+ } /* Loop to move along the subject string */++/* Control gets here from "break" a few lines above. If we have a match and+PCRE2_ENDANCHORED is set, the match fails. */++if (match_count >= 0 &&+ ((mb->moptions | mb->poptions) & PCRE2_ENDANCHORED) != 0 &&+ ptr < end_subject)+ match_count = PCRE2_ERROR_NOMATCH;++return match_count;+}++++/*************************************************+* Match a pattern using the DFA algorithm *+*************************************************/++/* This function matches a compiled pattern to a subject string, using the+alternate matching algorithm that finds all matches at once.++Arguments:+ code points to the compiled pattern+ subject subject string+ length length of subject string+ startoffset where to start matching in the subject+ options option bits+ match_data points to a match data structure+ gcontext points to a match context+ workspace pointer to workspace+ wscount size of workspace++Returns: > 0 => number of match offset pairs placed in offsets+ = 0 => offsets overflowed; longest matches are present+ -1 => failed to match+ < -1 => some kind of unexpected problem+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_dfa_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 *workspace, PCRE2_SIZE wscount)+{+int rc;+int was_zero_terminated = 0;++const pcre2_real_code *re = (const pcre2_real_code *)code;++PCRE2_SPTR start_match;+PCRE2_SPTR end_subject;+PCRE2_SPTR bumpalong_limit;+PCRE2_SPTR req_cu_ptr;++BOOL utf, anchored, startline, firstline;+BOOL has_first_cu = FALSE;+BOOL has_req_cu = FALSE;++#if PCRE2_CODE_UNIT_WIDTH == 8+BOOL memchr_not_found_first_cu = FALSE;+BOOL memchr_not_found_first_cu2 = FALSE;+#endif++PCRE2_UCHAR first_cu = 0;+PCRE2_UCHAR first_cu2 = 0;+PCRE2_UCHAR req_cu = 0;+PCRE2_UCHAR req_cu2 = 0;++const uint8_t *start_bits = NULL;++/* We need to have mb pointing 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;+dfa_match_block actual_match_block;+dfa_match_block *mb = &actual_match_block;++/* Set up a starting block of memory for use during recursive calls to+internal_dfa_match(). By putting this on the stack, it minimizes resource use+in the case when it is not needed. If this is too small, more memory is+obtained from the heap. At the start of each block is an anchor structure.*/++int base_recursion_workspace[RWS_BASE_SIZE];+RWS_anchor *rws = (RWS_anchor *)base_recursion_workspace;+rws->next = NULL;+rws->size = RWS_BASE_SIZE;+rws->free = RWS_BASE_SIZE - RWS_ANCHOR_SIZE;++/* 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;+ }++/* Plausibility checks */++if ((options & ~PUBLIC_DFA_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;+if (re == NULL || subject == NULL || workspace == NULL || match_data == NULL)+ return PCRE2_ERROR_NULL;+if (wscount < 20) return PCRE2_ERROR_DFA_WSSIZE;+if (start_offset > length) return PCRE2_ERROR_BADOFFSET;++/* Partial matching and PCRE2_ENDANCHORED are currently not allowed at the same+time. */++if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0 &&+ ((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)+ return PCRE2_ERROR_BADOPTION;++/* Invalid UTF support is not available for DFA matching. */++if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0)+ return PCRE2_ERROR_DFA_UINVALID_UTF;++/* Check that the first field in the block is the magic number. If it is not,+return with PCRE2_ERROR_BADMAGIC. */++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 can now be+transferred 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 restarting after a partial match, do some sanity checks on the contents+of the workspace. */++if ((options & PCRE2_DFA_RESTART) != 0)+ {+ if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 ||+ workspace[1] > (int)((wscount - 2)/INTS_PER_STATEBLOCK))+ return PCRE2_ERROR_DFA_BADRESTART;+ }++/* Set some local values */++utf = (re->overall_options & PCRE2_UTF) != 0;+start_match = subject + start_offset;+end_subject = subject + length;+req_cu_ptr = start_match - 1;+anchored = (options & (PCRE2_ANCHORED|PCRE2_DFA_RESTART)) != 0 ||+ (re->overall_options & PCRE2_ANCHORED) != 0;++/* The "must be at the start of a line" flags are used in a loop when finding+where to start. */++startline = (re->flags & PCRE2_STARTLINE) != 0;+firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;+bumpalong_limit = end_subject;++/* 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;+cb.capture_top = 1; /* No capture support */+cb.capture_last = 0;+cb.mark = NULL; /* No (*MARK) support */++/* Get data from the match context, if present, and fill in the remaining+fields in the match block. It is an error to set an offset limit without+setting the flag at compile time. */++if (mcontext == NULL)+ {+ mb->callout = NULL;+ mb->memctl = re->memctl;+ mb->match_limit = PRIV(default_match_context).match_limit;+ mb->match_limit_depth = PRIV(default_match_context).depth_limit;+ mb->heap_limit = PRIV(default_match_context).heap_limit;+ }+else+ {+ if (mcontext->offset_limit != PCRE2_UNSET)+ {+ if ((re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)+ return PCRE2_ERROR_BADOFFSETLIMIT;+ bumpalong_limit = subject + mcontext->offset_limit;+ }+ mb->callout = mcontext->callout;+ mb->callout_data = mcontext->callout_data;+ mb->memctl = mcontext->memctl;+ mb->match_limit = mcontext->match_limit;+ mb->match_limit_depth = mcontext->depth_limit;+ mb->heap_limit = mcontext->heap_limit;+ }++if (mb->match_limit > re->limit_match)+ mb->match_limit = re->limit_match;++if (mb->match_limit_depth > re->limit_depth)+ mb->match_limit_depth = re->limit_depth;++if (mb->heap_limit > re->limit_heap)+ mb->heap_limit = re->limit_heap;++mb->start_code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) ++ re->name_count * re->name_entry_size;+mb->tables = re->tables;+mb->start_subject = subject;+mb->end_subject = end_subject;+mb->start_offset = start_offset;+mb->allowemptypartial = (re->max_lookbehind > 0) ||+ (re->flags & PCRE2_MATCH_EMPTY) != 0;+mb->moptions = options;+mb->poptions = re->overall_options;+mb->match_call_count = 0;+mb->heap_used = 0;++/* 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;+ }++/* Check a UTF string for validity if required. For 8-bit and 16-bit strings,+we must also check that a starting offset does not point into the middle of a+multiunit character. We check only the portion of the subject that is going to+be inspected during matching - from the offset minus the maximum back reference+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_UNICODE+if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)+ {+ PCRE2_SPTR check_subject = start_match; /* start_match includes offset */++ if (start_offset > 0)+ {+#if PCRE2_CODE_UNIT_WIDTH != 32+ unsigned int i;+ if (start_match < end_subject && NOT_FIRSTCU(*start_match))+ return PCRE2_ERROR_BADUTFOFFSET;+ for (i = re->max_lookbehind; i > 0 && check_subject > subject; i--)+ {+ check_subject--;+ while (check_subject > subject &&+#if PCRE2_CODE_UNIT_WIDTH == 8+ (*check_subject & 0xc0) == 0x80)+#else /* 16-bit */+ (*check_subject & 0xfc00) == 0xdc00)+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ check_subject--;+ }+#else /* In the 32-bit library, one code unit equals one character. */+ check_subject -= re->max_lookbehind;+ if (check_subject < subject) check_subject = subject;+#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */+ }++ /* Validate the relevant portion of the subject. After an error, adjust the+ offset to be an absolute offset in the whole string. */++ match_data->rc = PRIV(valid_utf)(check_subject,+ length - (PCRE2_SIZE)(check_subject - subject), &(match_data->startchar));+ if (match_data->rc != 0)+ {+ match_data->startchar += (PCRE2_SIZE)(check_subject - subject);+ return match_data->rc;+ }+ }+#endif /* SUPPORT_UNICODE */++/* 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->tables + fcc_offset, first_cu);+#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (first_cu > 127 && !utf && (re->overall_options & PCRE2_UCP) != 0)+ first_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(first_cu);+#else+ if (first_cu > 127 && (utf || (re->overall_options & PCRE2_UCP) != 0))+ first_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(first_cu);+#endif+#endif /* SUPPORT_UNICODE */+ }+ }+else+ if (!startline && (re->flags & PCRE2_FIRSTMAPSET) != 0)+ start_bits = re->start_bitmap;++/* There may be a "last known required code unit" 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->tables + fcc_offset, req_cu);+#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (req_cu > 127 && !utf && (re->overall_options & PCRE2_UCP) != 0)+ req_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(req_cu);+#else+ if (req_cu > 127 && (utf || (re->overall_options & PCRE2_UCP) != 0))+ req_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(req_cu);+#endif+#endif /* SUPPORT_UNICODE */+ }+ }++/* If the match data block was previously used with PCRE2_COPY_MATCHED_SUBJECT,+free the memory that was obtained. */++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;+ }++/* Fill in fields that are always returned in the match data. */++match_data->code = re;+match_data->subject = NULL; /* Default for no match */+match_data->mark = NULL;+match_data->matchedby = PCRE2_MATCHEDBY_DFA_INTERPRETER;++/* Call the main matching function, looping for a non-anchored regex after a+failed match. If not restarting, perform certain optimizations at the start of+a match. */++for (;;)+ {+ /* ----------------- 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.+ The optimizations must also be avoided when restarting a DFA match. */++ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 &&+ (options & PCRE2_DFA_RESTART) == 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 optimization scans for a first code unit+ immediately after the first character of a newline (the first code unit can+ legitimately be a newline). If the match fails at the newline, later code+ breaks this 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) break;+ }+ }++ /* Not anchored. Advance to a unique first code unit if there is one. In+ 8-bit mode, the use of memchr() gives a big speed up, even though we have+ to call it twice in caseless mode, in order to find the earliest occurrence+ of the character in either of its cases. If a call to memchr() that+ searches the rest of the subject fails to find one case, remember that in+ order not to keep on repeating the search. This can make a huge difference+ when the strings are very long and only one case is present. */++ else+ {+ if (has_first_cu)+ {+ if (first_cu != first_cu2) /* Caseless */+ {+#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 /* 8-bit code units */+ PCRE2_SPTR pp1 = NULL;+ PCRE2_SPTR pp2 = NULL;+ PCRE2_SIZE cu2size = end_subject - start_match;++ if (!memchr_not_found_first_cu)+ {+ pp1 = memchr(start_match, first_cu, end_subject - start_match);+ if (pp1 == NULL) memchr_not_found_first_cu = TRUE;+ else cu2size = pp1 - start_match;+ }++ /* If pp1 is not NULL, we have arranged to search only as far as pp1,+ to see if the other case is earlier, so we can set "not found" only+ when both searches have returned NULL. */++ if (!memchr_not_found_first_cu2)+ {+ pp2 = memchr(start_match, first_cu2, cu2size);+ memchr_not_found_first_cu2 = (pp2 == NULL && pp1 == NULL);+ }++ if (pp1 == NULL)+ start_match = (pp2 == NULL)? end_subject : pp2;+ else+ start_match = (pp2 == NULL || pp1 < pp2)? pp1 : pp2;+#endif+ }++ /* The caseful case */++ else+ {+#if PCRE2_CODE_UNIT_WIDTH != 8+ while (start_match < end_subject && UCHAR21TEST(start_match) !=+ first_cu)+ start_match++;+#else /* 8-bit code units */+ 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 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->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) == 0 &&+ start_match >= mb->end_subject)+ 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 line. */++ if ((mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) == 0 &&+ start_match >= mb->end_subject)+ break;+ }+ } /* End of first code unit handling */++ /* Restore fudged end_subject */++ end_subject = mb->end_subject;++ /* The following two optimizations are disabled for partial matching. */++ if ((mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) == 0)+ {+ PCRE2_SPTR p;++ /* The minimum matching length is a lower bound; no actual string of that+ length may actually match the pattern. Although the value is, strictly,+ in characters, we treat it as code units to avoid spending too much time+ in this optimization. */++ if (end_subject - start_match < re->minlength) goto NOMATCH_EXIT;++ /* If req_cu is set, we know that that code unit must appear in the+ subject for the 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 cased/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+ 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 matching loop,+ forcing a match failure. */++ if (p >= end_subject) 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 loop if+ the start hasn't passed this code unit yet. */++ 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) break;++ /* OK, now we can do the business */++ mb->start_used_ptr = start_match;+ mb->last_used_ptr = start_match;+ mb->recursive = NULL;++ rc = internal_dfa_match(+ mb, /* fixed match data */+ mb->start_code, /* this subexpression's code */+ start_match, /* where we currently are */+ start_offset, /* start offset in subject */+ match_data->ovector, /* offset vector */+ (uint32_t)match_data->oveccount * 2, /* actual size of same */+ workspace, /* workspace vector */+ (int)wscount, /* size of same */+ 0, /* function recurse level */+ base_recursion_workspace); /* initial workspace for recursion */++ /* Anything other than "no match" means we are done, always; otherwise, carry+ on only if not anchored. */++ if (rc != PCRE2_ERROR_NOMATCH || anchored)+ {+ if (rc == PCRE2_ERROR_PARTIAL && match_data->oveccount > 0)+ {+ match_data->ovector[0] = (PCRE2_SIZE)(start_match - subject);+ match_data->ovector[1] = (PCRE2_SIZE)(end_subject - subject);+ }+ match_data->leftchar = (PCRE2_SIZE)(mb->start_used_ptr - subject);+ match_data->rightchar = (PCRE2_SIZE)( mb->last_used_ptr - subject);+ match_data->startchar = (PCRE2_SIZE)(start_match - subject);+ match_data->rc = rc;++ 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;+ }+ else+ {+ if (rc >= 0 || rc == PCRE2_ERROR_PARTIAL) match_data->subject = subject;+ }+ goto EXIT;+ }++ /* Advance to the next subject character unless we are at the end of a line+ and firstline is set. */++ if (firstline && IS_NEWLINE(start_match)) break;+ start_match++;+#ifdef SUPPORT_UNICODE+ if (utf)+ {+ ACROSSCHAR(start_match < end_subject, start_match, start_match++);+ }+#endif+ if (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 character. */++ if (UCHAR21TEST(start_match - 1) == CHAR_CR &&+ start_match < end_subject &&+ UCHAR21TEST(start_match) == CHAR_NL &&+ (re->flags & PCRE2_HASCRORLF) == 0 &&+ (mb->nltype == NLTYPE_ANY ||+ mb->nltype == NLTYPE_ANYCRLF ||+ mb->nllen == 2))+ start_match++;++ } /* "Bumpalong" loop */++NOMATCH_EXIT:+rc = PCRE2_ERROR_NOMATCH;++EXIT:+while (rws->next != NULL)+ {+ RWS_anchor *next = rws->next;+ rws->next = next->next;+ mb->memctl.free(next, mb->memctl.memory_data);+ }++return rc;+}++/* End of pcre2_dfa_match.c */
+ src/c/pcre2/src/pcre2_dftables.c view
@@ -0,0 +1,303 @@+/*************************************************+* 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) 2016-2020 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.+-----------------------------------------------------------------------------+*/+++/* This is a freestanding support program to generate a file containing+character tables for PCRE2. The tables are built using the pcre2_maketables()+function, which is part of the PCRE2 API. By default, the system's "C" locale+is used rather than what the building user happens to have set, but the -L+option can be used to select the current locale from the LC_ALL environment+variable. By default, the tables are written in source form, but if -b is+given, they are written in binary. */++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include <ctype.h>+#include <stdio.h>+#include <string.h>+#include <locale.h>++#define PCRE2_CODE_UNIT_WIDTH 0 /* Must be set, but not relevant here */+#include "pcre2_internal.h"++#define PCRE2_DFTABLES /* pcre2_maketables.c notices this */+#include "pcre2_maketables.c"+++static char *classlist[] =+ {+ "space", "xdigit", "digit", "upper", "lower",+ "word", "graph", "print", "punct", "cntrl"+ };++++/*************************************************+* Usage *+*************************************************/++static void+usage(void)+{+(void)fprintf(stderr,+ "Usage: pcre2_dftables [options] <output file>\n"+ " -b Write output in binary (default is source code)\n"+ " -L Use locale from LC_ALL (default is \"C\" locale)\n"+ );+}++++/*************************************************+* Entry point *+*************************************************/++int main(int argc, char **argv)+{+FILE *f;+int i;+int nclass = 0;+BOOL binary = FALSE;+char *env = "C";+const unsigned char *tables;+const unsigned char *base_of_tables;++/* Process options */++for (i = 1; i < argc; i++)+ {+ unsigned char *arg = (unsigned char *)argv[i];+ if (*arg != '-') break;++ if (strcmp(arg, "-help") == 0 || strcmp(arg, "--help") == 0)+ {+ usage();+ return 0;+ }++ else if (strcmp(arg, "-L") == 0)+ {+ if (setlocale(LC_ALL, "") == NULL)+ {+ (void)fprintf(stderr, "pcre2_dftables: setlocale() failed\n");+ return 1;+ }+ env = getenv("LC_ALL");+ }++ else if (strcmp(arg, "-b") == 0)+ binary = TRUE;++ else+ {+ (void)fprintf(stderr, "pcre2_dftables: unrecognized option %s\n", arg);+ return 1;+ }+ }++if (i != argc - 1)+ {+ (void)fprintf(stderr, "pcre2_dftables: one filename argument is required\n");+ return 1;+ }++/* Make the tables */++tables = maketables();+base_of_tables = tables;++f = fopen(argv[i], "wb");+if (f == NULL)+ {+ fprintf(stderr, "pcre2_dftables: failed to open %s for writing\n", argv[1]);+ return 1;+ }++/* If -b was specified, we write the tables in binary. */++if (binary)+ {+ int yield = 0;+ size_t len = fwrite(tables, 1, TABLES_LENGTH, f);+ if (len != TABLES_LENGTH)+ {+ (void)fprintf(stderr, "pcre2_dftables: fwrite() returned wrong length %d "+ "instead of %d\n", (int)len, TABLES_LENGTH);+ yield = 1;+ }+ fclose(f);+ free((void *)base_of_tables);+ return yield;+ }++/* Write the tables as source code for inclusion in the PCRE2 library. There+are several fprintf() calls here, because gcc in pedantic mode complains about+the very long string otherwise. */++(void)fprintf(f,+ "/*************************************************\n"+ "* Perl-Compatible Regular Expressions *\n"+ "*************************************************/\n\n"+ "/* This file was automatically written by the pcre2_dftables auxiliary\n"+ "program. It contains character tables that are used when no external\n"+ "tables are passed to PCRE2 by the application that calls it. The tables\n"+ "are used only for characters whose code values are less than 256. */\n\n");++(void)fprintf(f,+ "/* This set of tables was written in the %s locale. */\n\n", env);++(void)fprintf(f,+ "/* The pcre2_ftables program (which is distributed with PCRE2) can be used\n"+ "to build alternative versions of this file. This is necessary if you are\n"+ "running in an EBCDIC environment, or if you want to default to a different\n"+ "encoding, for example ISO-8859-1. When pcre2_dftables is run, it creates\n"+ "these tables in the \"C\" locale by default. This happens automatically if\n"+ "PCRE2 is configured with --enable-rebuild-chartables. However, you can run\n"+ "pcre2_dftables manually with the -L option to build tables using the LC_ALL\n"+ "locale. */\n\n");++/* Force config.h in z/OS */++#if defined NATIVE_ZOS+(void)fprintf(f,+ "/* For z/OS, config.h is forced */\n"+ "#ifndef HAVE_CONFIG_H\n"+ "#define HAVE_CONFIG_H 1\n"+ "#endif\n\n");+#endif++(void)fprintf(f,+ "/* The following #include is present because without it gcc 4.x may remove\n"+ "the array definition from the final binary if PCRE2 is built into a static\n"+ "library and dead code stripping is activated. This leads to link errors.\n"+ "Pulling in the header ensures that the array gets flagged as \"someone\n"+ "outside this compilation unit might reference this\" and so it will always\n"+ "be supplied to the linker. */\n\n");++(void)fprintf(f,+ "#ifdef HAVE_CONFIG_H\n"+ "#include \"config.h\"\n"+ "#endif\n\n"+ "#include \"pcre2_internal.h\"\n\n");++(void)fprintf(f,+ "const uint8_t PRIV(default_tables)[] = {\n\n"+ "/* This table is a lower casing table. */\n\n");++(void)fprintf(f, " ");+for (i = 0; i < 256; i++)+ {+ if ((i & 7) == 0 && i != 0) fprintf(f, "\n ");+ fprintf(f, "%3d", *tables++);+ if (i != 255) fprintf(f, ",");+ }+(void)fprintf(f, ",\n\n");++(void)fprintf(f, "/* This table is a case flipping table. */\n\n");++(void)fprintf(f, " ");+for (i = 0; i < 256; i++)+ {+ if ((i & 7) == 0 && i != 0) fprintf(f, "\n ");+ fprintf(f, "%3d", *tables++);+ if (i != 255) fprintf(f, ",");+ }+(void)fprintf(f, ",\n\n");++(void)fprintf(f,+ "/* This table contains bit maps for various character classes. Each map is 32\n"+ "bytes long and the bits run from the least significant end of each byte. The\n"+ "classes that have their own maps are: space, xdigit, digit, upper, lower, word,\n"+ "graph, print, punct, and cntrl. Other classes are built from combinations. */\n\n");++(void)fprintf(f, " ");+for (i = 0; i < cbit_length; i++)+ {+ if ((i & 7) == 0 && i != 0)+ {+ if ((i & 31) == 0) (void)fprintf(f, "\n");+ if ((i & 24) == 8) (void)fprintf(f, " /* %s */", classlist[nclass++]);+ (void)fprintf(f, "\n ");+ }+ (void)fprintf(f, "0x%02x", *tables++);+ if (i != cbit_length - 1) (void)fprintf(f, ",");+ }+(void)fprintf(f, ",\n\n");++(void)fprintf(f,+ "/* This table identifies various classes of character by individual bits:\n"+ " 0x%02x white space character\n"+ " 0x%02x letter\n"+ " 0x%02x lower case letter\n"+ " 0x%02x decimal digit\n"+ " 0x%02x alphanumeric or '_'\n*/\n\n",+ ctype_space, ctype_letter, ctype_lcletter, ctype_digit, ctype_word);++(void)fprintf(f, " ");+for (i = 0; i < 256; i++)+ {+ if ((i & 7) == 0 && i != 0)+ {+ (void)fprintf(f, " /* ");+ if (isprint(i-8)) (void)fprintf(f, " %c -", i-8);+ else (void)fprintf(f, "%3d-", i-8);+ if (isprint(i-1)) (void)fprintf(f, " %c ", i-1);+ else (void)fprintf(f, "%3d", i-1);+ (void)fprintf(f, " */\n ");+ }+ (void)fprintf(f, "0x%02x", *tables++);+ if (i != 255) (void)fprintf(f, ",");+ }++(void)fprintf(f, "};/* ");+if (isprint(i-8)) (void)fprintf(f, " %c -", i-8);+ else (void)fprintf(f, "%3d-", i-8);+if (isprint(i-1)) (void)fprintf(f, " %c ", i-1);+ else (void)fprintf(f, "%3d", i-1);+(void)fprintf(f, " */\n\n/* End of pcre2_chartables.c */\n");++fclose(f);+free((void *)base_of_tables);+return 0;+}++/* End of pcre2_dftables.c */
+ src/c/pcre2/src/pcre2_error.c view
@@ -0,0 +1,340 @@+/*************************************************+* 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) 2016-2019 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++#include "pcre2_internal.h"++#define STRING(a) # a+#define XSTRING(s) STRING(s)++/* The texts of compile-time error messages. Compile-time error numbers start+at COMPILE_ERROR_BASE (100).++This used to be a table of strings, but in order to reduce the number of+relocations needed when a shared library is loaded dynamically, it is now one+long string. We cannot use a table of offsets, because the lengths of inserts+such as XSTRING(MAX_NAME_SIZE) are not known. Instead,+pcre2_get_error_message() counts through to the one it wants - this isn't a+performance issue because these strings are used only when there is an error.++Each substring ends with \0 to insert a null character. This includes the final+substring, so that the whole string ends with \0\0, which can be detected when+counting through. */++static const unsigned char compile_error_texts[] =+ "no error\0"+ "\\ at end of pattern\0"+ "\\c at end of pattern\0"+ "unrecognized character follows \\\0"+ "numbers out of order in {} quantifier\0"+ /* 5 */+ "number too big in {} quantifier\0"+ "missing terminating ] for character class\0"+ "escape sequence is invalid in character class\0"+ "range out of order in character class\0"+ "quantifier does not follow a repeatable item\0"+ /* 10 */+ "internal error: unexpected repeat\0"+ "unrecognized character after (? or (?-\0"+ "POSIX named classes are supported only within a class\0"+ "POSIX collating elements are not supported\0"+ "missing closing parenthesis\0"+ /* 15 */+ "reference to non-existent subpattern\0"+ "pattern passed as NULL\0"+ "unrecognised compile-time option bit(s)\0"+ "missing ) after (?# comment\0"+ "parentheses are too deeply nested\0"+ /* 20 */+ "regular expression is too large\0"+ "failed to allocate heap memory\0"+ "unmatched closing parenthesis\0"+ "internal error: code overflow\0"+ "missing closing parenthesis for condition\0"+ /* 25 */+ "lookbehind assertion is not fixed length\0"+ "a relative value of zero is not allowed\0"+ "conditional subpattern contains more than two branches\0"+ "assertion expected after (?( or (?(?C)\0"+ "digit expected after (?+ or (?-\0"+ /* 30 */+ "unknown POSIX class name\0"+ "internal error in pcre2_study(): should not occur\0"+ "this version of PCRE2 does not have Unicode support\0"+ "parentheses are too deeply nested (stack check)\0"+ "character code point value in \\x{} or \\o{} is too large\0"+ /* 35 */+ "lookbehind is too complicated\0"+ "\\C is not allowed in a lookbehind assertion in UTF-" XSTRING(PCRE2_CODE_UNIT_WIDTH) " mode\0"+ "PCRE2 does not support \\F, \\L, \\l, \\N{name}, \\U, or \\u\0"+ "number after (?C is greater than 255\0"+ "closing parenthesis for (?C expected\0"+ /* 40 */+ "invalid escape sequence in (*VERB) name\0"+ "unrecognized character after (?P\0"+ "syntax error in subpattern name (missing terminator?)\0"+ "two named subpatterns have the same name (PCRE2_DUPNAMES not set)\0"+ "subpattern name must start with a non-digit\0"+ /* 45 */+ "this version of PCRE2 does not have support for \\P, \\p, or \\X\0"+ "malformed \\P or \\p sequence\0"+ "unknown property name after \\P or \\p\0"+ "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " code units)\0"+ "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0"+ /* 50 */+ "invalid range in character class\0"+ "octal value is greater than \\377 in 8-bit non-UTF-8 mode\0"+ "internal error: overran compiling workspace\0"+ "internal error: previously-checked referenced subpattern not found\0"+ "DEFINE subpattern contains more than one branch\0"+ /* 55 */+ "missing opening brace after \\o\0"+ "internal error: unknown newline setting\0"+ "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number\0"+ "(?R (recursive pattern call) must be followed by a closing parenthesis\0"+ /* "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)\0" */+ "obsolete error (should not occur)\0" /* Was the above */+ /* 60 */+ "(*VERB) not recognized or malformed\0"+ "subpattern number is too big\0"+ "subpattern name expected\0"+ "internal error: parsed pattern overflow\0"+ "non-octal character in \\o{} (closing brace missing?)\0"+ /* 65 */+ "different names for subpatterns of the same number are not allowed\0"+ "(*MARK) must have an argument\0"+ "non-hex character in \\x{} (closing brace missing?)\0"+#ifndef EBCDIC+ "\\c must be followed by a printable ASCII character\0"+#else+ "\\c must be followed by a letter or one of [\\]^_?\0"+#endif+ "\\k is not followed by a braced, angle-bracketed, or quoted name\0"+ /* 70 */+ "internal error: unknown meta code in check_lookbehinds()\0"+ "\\N is not supported in a class\0"+ "callout string is too long\0"+ "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)\0"+ "using UTF is disabled by the application\0"+ /* 75 */+ "using UCP is disabled by the application\0"+ "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0"+ "character code point value in \\u.... sequence is too large\0"+ "digits missing in \\x{} or \\o{} or \\N{U+}\0"+ "syntax error or number too big in (?(VERSION condition\0"+ /* 80 */+ "internal error: unknown opcode in auto_possessify()\0"+ "missing terminating delimiter for callout with string argument\0"+ "unrecognized string delimiter follows (?C\0"+ "using \\C is disabled by the application\0"+ "(?| and/or (?J: or (?x: parentheses are too deeply nested\0"+ /* 85 */+ "using \\C is disabled in this PCRE2 library\0"+ "regular expression is too complicated\0"+ "lookbehind assertion is too long\0"+ "pattern string is longer than the limit set by the application\0"+ "internal error: unknown code in parsed pattern\0"+ /* 90 */+ "internal error: bad code value in parsed_skip()\0"+ "PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not allowed in UTF-16 mode\0"+ "invalid option bits with PCRE2_LITERAL\0"+ "\\N{U+dddd} is supported only in Unicode (UTF) mode\0"+ "invalid hyphen in option setting\0"+ /* 95 */+ "(*alpha_assertion) not recognized\0"+ "script runs require Unicode support, which this version of PCRE2 does not have\0"+ "too many capturing groups (maximum 65535)\0"+ "atomic assertion expected after (?( or (?(?C)\0"+ ;++/* Match-time and UTF error texts are in the same format. */++static const unsigned char match_error_texts[] =+ "no error\0"+ "no match\0"+ "partial match\0"+ "UTF-8 error: 1 byte missing at end\0"+ "UTF-8 error: 2 bytes missing at end\0"+ /* 5 */+ "UTF-8 error: 3 bytes missing at end\0"+ "UTF-8 error: 4 bytes missing at end\0"+ "UTF-8 error: 5 bytes missing at end\0"+ "UTF-8 error: byte 2 top bits not 0x80\0"+ "UTF-8 error: byte 3 top bits not 0x80\0"+ /* 10 */+ "UTF-8 error: byte 4 top bits not 0x80\0"+ "UTF-8 error: byte 5 top bits not 0x80\0"+ "UTF-8 error: byte 6 top bits not 0x80\0"+ "UTF-8 error: 5-byte character is not allowed (RFC 3629)\0"+ "UTF-8 error: 6-byte character is not allowed (RFC 3629)\0"+ /* 15 */+ "UTF-8 error: code points greater than 0x10ffff are not defined\0"+ "UTF-8 error: code points 0xd800-0xdfff are not defined\0"+ "UTF-8 error: overlong 2-byte sequence\0"+ "UTF-8 error: overlong 3-byte sequence\0"+ "UTF-8 error: overlong 4-byte sequence\0"+ /* 20 */+ "UTF-8 error: overlong 5-byte sequence\0"+ "UTF-8 error: overlong 6-byte sequence\0"+ "UTF-8 error: isolated byte with 0x80 bit set\0"+ "UTF-8 error: illegal byte (0xfe or 0xff)\0"+ "UTF-16 error: missing low surrogate at end\0"+ /* 25 */+ "UTF-16 error: invalid low surrogate\0"+ "UTF-16 error: isolated low surrogate\0"+ "UTF-32 error: code points 0xd800-0xdfff are not defined\0"+ "UTF-32 error: code points greater than 0x10ffff are not defined\0"+ "bad data value\0"+ /* 30 */+ "patterns do not all use the same character tables\0"+ "magic number missing\0"+ "pattern compiled in wrong mode: 8/16/32-bit error\0"+ "bad offset value\0"+ "bad option value\0"+ /* 35 */+ "invalid replacement string\0"+ "bad offset into UTF string\0"+ "callout error code\0" /* Never returned by PCRE2 itself */+ "invalid data in workspace for DFA restart\0"+ "too much recursion for DFA matching\0"+ /* 40 */+ "backreference condition or recursion test is not supported for DFA matching\0"+ "function is not supported for DFA matching\0"+ "pattern contains an item that is not supported for DFA matching\0"+ "workspace size exceeded in DFA matching\0"+ "internal error - pattern overwritten?\0"+ /* 45 */+ "bad JIT option\0"+ "JIT stack limit reached\0"+ "match limit exceeded\0"+ "no more memory\0"+ "unknown substring\0"+ /* 50 */+ "non-unique substring name\0"+ "NULL argument passed\0"+ "nested recursion at the same subject position\0"+ "matching depth limit exceeded\0"+ "requested value is not available\0"+ /* 55 */+ "requested value is not set\0"+ "offset limit set without PCRE2_USE_OFFSET_LIMIT\0"+ "bad escape sequence in replacement string\0"+ "expected closing curly bracket in replacement string\0"+ "bad substitution in replacement string\0"+ /* 60 */+ "match with end before start or start moved backwards is not supported\0"+ "too many replacements (more than INT_MAX)\0"+ "bad serialized data\0"+ "heap limit exceeded\0"+ "invalid syntax\0"+ /* 65 */+ "internal error - duplicate substitution match\0"+ "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching\0"+ ;+++/*************************************************+* Return error message *+*************************************************/++/* This function copies an error message into a buffer whose units are of an+appropriate width. Error numbers are positive for compile-time errors, and+negative for match-time errors (except for UTF errors), but the numbers are all+distinct.++Arguments:+ enumber error number+ buffer where to put the message (zero terminated)+ size size of the buffer in code units++Returns: length of message if all is well+ negative on error+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_get_error_message(int enumber, PCRE2_UCHAR *buffer, PCRE2_SIZE size)+{+const unsigned char *message;+PCRE2_SIZE i;+int n;++if (size == 0) return PCRE2_ERROR_NOMEMORY;++if (enumber >= COMPILE_ERROR_BASE) /* Compile error */+ {+ message = compile_error_texts;+ n = enumber - COMPILE_ERROR_BASE;+ }+else if (enumber < 0) /* Match or UTF error */+ {+ message = match_error_texts;+ n = -enumber;+ }+else /* Invalid error number */+ {+ message = (unsigned char *)"\0"; /* Empty message list */+ n = 1;+ }++for (; n > 0; n--)+ {+ while (*message++ != CHAR_NUL) {};+ if (*message == CHAR_NUL) return PCRE2_ERROR_BADDATA;+ }++for (i = 0; *message != 0; i++)+ {+ if (i >= size - 1)+ {+ buffer[i] = 0; /* Terminate partial message */+ return PCRE2_ERROR_NOMEMORY;+ }+ buffer[i] = *message++;+ }++buffer[i] = 0;+return (int)i;+}++/* End of pcre2_error.c */
+ src/c/pcre2/src/pcre2_extuni.c view
@@ -0,0 +1,148 @@+/*************************************************+* 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) 2016-2019 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.+-----------------------------------------------------------------------------+*/++/* This module contains an internal function that is used to match a Unicode+extended grapheme sequence. It is used by both pcre2_match() and+pcre2_def_match(). However, it is called only when Unicode support is being+compiled. Nevertheless, we provide a dummy function when there is no Unicode+support, because some compilers do not like functionless source files. */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif+++#include "pcre2_internal.h"+++/* Dummy function */++#ifndef SUPPORT_UNICODE+PCRE2_SPTR+PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject,+ PCRE2_SPTR end_subject, BOOL utf, int *xcount)+{+(void)c;+(void)eptr;+(void)start_subject;+(void)end_subject;+(void)utf;+(void)xcount;+return NULL;+}+#else+++/*************************************************+* Match an extended grapheme sequence *+*************************************************/++/*+Arguments:+ c the first character+ eptr pointer to next character+ start_subject pointer to start of subject+ end_subject pointer to end of subject+ utf TRUE if in UTF mode+ xcount pointer to count of additional characters,+ or NULL if count not needed++Returns: pointer after the end of the sequence+*/++PCRE2_SPTR+PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject,+ PCRE2_SPTR end_subject, BOOL utf, int *xcount)+{+int lgb = UCD_GRAPHBREAK(c);++while (eptr < end_subject)+ {+ int rgb;+ int len = 1;+ if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }+ rgb = UCD_GRAPHBREAK(c);+ if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;++ /* Not breaking between Regional Indicators is allowed only if there+ are an even number of preceding RIs. */++ if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)+ {+ int ricount = 0;+ PCRE2_SPTR bptr = eptr - 1;+ if (utf) BACKCHAR(bptr);++ /* bptr is pointing to the left-hand character */++ while (bptr > start_subject)+ {+ bptr--;+ if (utf)+ {+ BACKCHAR(bptr);+ GETCHAR(c, bptr);+ }+ else+ c = *bptr;+ if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break;+ ricount++;+ }+ if ((ricount & 1) != 0) break; /* Grapheme break required */+ }++ /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this+ allows any number of them before a following Extended_Pictographic. */++ if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||+ lgb != ucp_gbExtended_Pictographic)+ lgb = rgb;++ eptr += len;+ if (xcount != NULL) *xcount += 1;+ }++return eptr;+}++#endif /* SUPPORT_UNICODE */++/* End of pcre2_extuni.c */
+ src/c/pcre2/src/pcre2_find_bracket.c view
@@ -0,0 +1,219 @@+/*************************************************+* 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) 2016-2018 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.+-----------------------------------------------------------------------------+*/+++/* This module contains a single function that scans through a compiled pattern+until it finds a capturing bracket with the given number, or, if the number is+negative, an instance of OP_REVERSE for a lookbehind. The function is called+from pcre2_compile.c and also from pcre2_study.c when finding the minimum+matching length. */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include "pcre2_internal.h"+++/*************************************************+* Scan compiled regex for specific bracket *+*************************************************/++/*+Arguments:+ code points to start of expression+ utf TRUE in UTF mode+ number the required bracket number or negative to find a lookbehind++Returns: pointer to the opcode for the bracket, or NULL if not found+*/++PCRE2_SPTR+PRIV(find_bracket)(PCRE2_SPTR code, BOOL utf, int number)+{+for (;;)+ {+ PCRE2_UCHAR c = *code;++ if (c == OP_END) return NULL;++ /* XCLASS is used for classes that cannot be represented just by a bit map.+ This includes negated single high-valued characters. CALLOUT_STR is used for+ callouts with string arguments. In both cases the length in the table is+ zero; the actual length is stored in the compiled code. */++ if (c == OP_XCLASS) code += GET(code, 1);+ else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE);++ /* Handle lookbehind */++ else if (c == OP_REVERSE)+ {+ if (number < 0) return (PCRE2_UCHAR *)code;+ code += PRIV(OP_lengths)[c];+ }++ /* Handle capturing bracket */++ else if (c == OP_CBRA || c == OP_SCBRA ||+ c == OP_CBRAPOS || c == OP_SCBRAPOS)+ {+ int n = (int)GET2(code, 1+LINK_SIZE);+ if (n == number) return (PCRE2_UCHAR *)code;+ code += PRIV(OP_lengths)[c];+ }++ /* Otherwise, we can get the item's length from the table, except that for+ repeated character types, we have to test for \p and \P, which have an extra+ two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we+ must add in its length. */++ else+ {+ switch(c)+ {+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;+ break;++ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ case OP_TYPEPOSUPTO:+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)+ code += 2;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ code += code[1];+ break;+ }++ /* Add in the fixed length from the table */++ code += PRIV(OP_lengths)[c];++ /* In UTF-8 and UTF-16 modes, opcodes that are followed by a character may be+ followed by a multi-byte character. The length in the table is a minimum, so+ we have to arrange to skip the extra bytes. */++#ifdef MAYBE_UTF_MULTI+ if (utf) switch(c)+ {+ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ case OP_EXACT:+ case OP_EXACTI:+ case OP_NOTEXACT:+ case OP_NOTEXACTI:+ case OP_UPTO:+ case OP_UPTOI:+ case OP_NOTUPTO:+ case OP_NOTUPTOI:+ case OP_MINUPTO:+ case OP_MINUPTOI:+ case OP_NOTMINUPTO:+ case OP_NOTMINUPTOI:+ case OP_POSUPTO:+ case OP_POSUPTOI:+ case OP_NOTPOSUPTO:+ case OP_NOTPOSUPTOI:+ case OP_STAR:+ case OP_STARI:+ case OP_NOTSTAR:+ case OP_NOTSTARI:+ case OP_MINSTAR:+ case OP_MINSTARI:+ case OP_NOTMINSTAR:+ case OP_NOTMINSTARI:+ case OP_POSSTAR:+ case OP_POSSTARI:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSSTARI:+ case OP_PLUS:+ case OP_PLUSI:+ case OP_NOTPLUS:+ case OP_NOTPLUSI:+ case OP_MINPLUS:+ case OP_MINPLUSI:+ case OP_NOTMINPLUS:+ case OP_NOTMINPLUSI:+ case OP_POSPLUS:+ case OP_POSPLUSI:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSPLUSI:+ case OP_QUERY:+ case OP_QUERYI:+ case OP_NOTQUERY:+ case OP_NOTQUERYI:+ case OP_MINQUERY:+ case OP_MINQUERYI:+ case OP_NOTMINQUERY:+ case OP_NOTMINQUERYI:+ case OP_POSQUERY:+ case OP_POSQUERYI:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSQUERYI:+ if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);+ break;+ }+#else+ (void)(utf); /* Keep compiler happy by referencing function argument */+#endif /* MAYBE_UTF_MULTI */+ }+ }+}++/* End of pcre2_find_bracket.c */
+ src/c/pcre2/src/pcre2_fuzzsupport.c view
@@ -0,0 +1,365 @@+/***************************************************************************+Fuzzer driver for PCRE2. Given an arbitrary string of bytes and a length, it+tries to compile and match it, deriving options from the string itself. If+STANDALONE is defined, a main program that calls the driver with the contents+of specified files is compiled, and commentary on what is happening is output.+If an argument starts with '=' the rest of it it is taken as a literal string+rather than a file name. This allows easy testing of short strings.++Written by Philip Hazel, October 2016+***************************************************************************/++#include <errno.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>++#define PCRE2_CODE_UNIT_WIDTH 8+#include "pcre2.h"++#define MAX_MATCH_SIZE 1000++#define DFA_WORKSPACE_COUNT 100++#define ALLOWED_COMPILE_OPTIONS \+ (PCRE2_ANCHORED|PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \+ PCRE2_ALT_VERBNAMES|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_DOLLAR_ENDONLY| \+ PCRE2_DOTALL|PCRE2_DUPNAMES|PCRE2_ENDANCHORED|PCRE2_EXTENDED|PCRE2_FIRSTLINE| \+ PCRE2_MATCH_UNSET_BACKREF|PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C| \+ PCRE2_NO_AUTO_CAPTURE| \+ PCRE2_NO_AUTO_POSSESS|PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_NO_START_OPTIMIZE| \+ PCRE2_UCP|PCRE2_UNGREEDY|PCRE2_USE_OFFSET_LIMIT| \+ PCRE2_UTF)++#define ALLOWED_MATCH_OPTIONS \+ (PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \+ PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_HARD| \+ PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT)++/* This is the callout function. Its only purpose is to halt matching if there+are more than 100 callouts, as one way of stopping too much time being spent on+fruitless matches. The callout data is a pointer to the counter. */++static int callout_function(pcre2_callout_block *cb, void *callout_data)+{+(void)cb; /* Avoid unused parameter warning */+*((uint32_t *)callout_data) += 1;+return (*((uint32_t *)callout_data) > 100)? PCRE2_ERROR_CALLOUT : 0;+}++/* Putting in this apparently unnecessary prototype prevents gcc from giving a+"no previous prototype" warning when compiling at high warning level. */++int LLVMFuzzerTestOneInput(const unsigned char *, size_t);++/* Here's the driving function. */++int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size)+{+uint32_t compile_options;+uint32_t match_options;+pcre2_match_data *match_data = NULL;+pcre2_match_context *match_context = NULL;+size_t match_size;+int dfa_workspace[DFA_WORKSPACE_COUNT];+int r1, r2;+int i;++if (size < 1) return 0;++/* Limiting the length of the subject for matching stops fruitless searches+in large trees taking too much time. */++match_size = (size > MAX_MATCH_SIZE)? MAX_MATCH_SIZE : size;++/* Figure out some options to use. Initialize the random number to ensure+repeatability. Ensure that we get a 32-bit unsigned random number for testing+options. (RAND_MAX is required to be at least 32767, but is commonly+2147483647, which excludes the top bit.) */++srand((unsigned int)(data[size/2]));+r1 = rand();+r2 = rand();++/* Ensure that all undefined option bits are zero (waste of time trying them)+and also that PCRE2_NO_UTF_CHECK is unset, as there is no guarantee that the+input is UTF-8. Also unset PCRE2_NEVER_UTF and PCRE2_NEVER_UCP as there is no+reason to disallow UTF and UCP. Force PCRE2_NEVER_BACKSLASH_C to be set because+\C in random patterns is highly likely to cause a crash. */++compile_options =+ ((((uint32_t)r1 << 16) | ((uint32_t)r2 & 0xffff)) & ALLOWED_COMPILE_OPTIONS) |+ PCRE2_NEVER_BACKSLASH_C;+ +match_options =+ ((((uint32_t)r1 << 16) | ((uint32_t)r2 & 0xffff)) & ALLOWED_MATCH_OPTIONS);+ +/* Discard partial matching if PCRE2_ENDANCHORED is set, because they are not+allowed together and just give an immediate error return. */++if (((compile_options|match_options) & PCRE2_ENDANCHORED) != 0)+ match_options &= ~(PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT); ++/* Do the compile with and without the options, and after a successful compile,+likewise do the match with and without the options. */++for (i = 0; i < 2; i++)+ {+ uint32_t callout_count;+ int errorcode;+ PCRE2_SIZE erroroffset;+ pcre2_code *code;++#ifdef STANDALONE+ printf("Compile options %.8x never_backslash_c", compile_options);+ printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",+ ((compile_options & PCRE2_ALT_BSUX) != 0)? ",alt_bsux" : "",+ ((compile_options & PCRE2_ALT_CIRCUMFLEX) != 0)? ",alt_circumflex" : "",+ ((compile_options & PCRE2_ALT_VERBNAMES) != 0)? ",alt_verbnames" : "",+ ((compile_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)? ",allow_empty_class" : "",+ ((compile_options & PCRE2_ANCHORED) != 0)? ",anchored" : "",+ ((compile_options & PCRE2_AUTO_CALLOUT) != 0)? ",auto_callout" : "",+ ((compile_options & PCRE2_CASELESS) != 0)? ",caseless" : "",+ ((compile_options & PCRE2_DOLLAR_ENDONLY) != 0)? ",dollar_endonly" : "",+ ((compile_options & PCRE2_DOTALL) != 0)? ",dotall" : "",+ ((compile_options & PCRE2_DUPNAMES) != 0)? ",dupnames" : "",+ ((compile_options & PCRE2_ENDANCHORED) != 0)? ",endanchored" : "",+ ((compile_options & PCRE2_EXTENDED) != 0)? ",extended" : "",+ ((compile_options & PCRE2_FIRSTLINE) != 0)? ",firstline" : "",+ ((compile_options & PCRE2_MATCH_UNSET_BACKREF) != 0)? ",match_unset_backref" : "",+ ((compile_options & PCRE2_MULTILINE) != 0)? ",multiline" : "",+ ((compile_options & PCRE2_NEVER_UCP) != 0)? ",never_ucp" : "",+ ((compile_options & PCRE2_NEVER_UTF) != 0)? ",never_utf" : "",+ ((compile_options & PCRE2_NO_AUTO_CAPTURE) != 0)? ",no_auto_capture" : "",+ ((compile_options & PCRE2_NO_AUTO_POSSESS) != 0)? ",no_auto_possess" : "",+ ((compile_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)? ",no_dotstar_anchor" : "",+ ((compile_options & PCRE2_NO_UTF_CHECK) != 0)? ",no_utf_check" : "",+ ((compile_options & PCRE2_NO_START_OPTIMIZE) != 0)? ",no_start_optimize" : "",+ ((compile_options & PCRE2_UCP) != 0)? ",ucp" : "",+ ((compile_options & PCRE2_UNGREEDY) != 0)? ",ungreedy" : "",+ ((compile_options & PCRE2_USE_OFFSET_LIMIT) != 0)? ",use_offset_limit" : "",+ ((compile_options & PCRE2_UTF) != 0)? ",utf" : "");+#endif++ code = pcre2_compile((PCRE2_SPTR)data, (PCRE2_SIZE)size, compile_options,+ &errorcode, &erroroffset, NULL);++ /* Compilation succeeded */++ if (code != NULL)+ {+ int j;+ uint32_t save_match_options = match_options;++ /* Create match data and context blocks only when we first need them. Set+ low match and depth limits to avoid wasting too much searching large+ pattern trees. Almost all matches are going to fail. */++ if (match_data == NULL)+ {+ match_data = pcre2_match_data_create(32, NULL);+ if (match_data == NULL)+ {+#ifdef STANDALONE+ printf("** Failed to create match data block\n");+#endif+ return 0;+ }+ }++ if (match_context == NULL)+ {+ match_context = pcre2_match_context_create(NULL);+ if (match_context == NULL)+ {+#ifdef STANDALONE+ printf("** Failed to create match context block\n");+#endif+ return 0;+ }+ (void)pcre2_set_match_limit(match_context, 100);+ (void)pcre2_set_depth_limit(match_context, 100);+ (void)pcre2_set_callout(match_context, callout_function, &callout_count);+ }++ /* Match twice, with and without options. */++ for (j = 0; j < 2; j++)+ {+#ifdef STANDALONE+ printf("Match options %.8x", match_options);+ printf("%s%s%s%s%s%s%s%s%s%s\n",+ ((match_options & PCRE2_ANCHORED) != 0)? ",anchored" : "",+ ((match_options & PCRE2_ENDANCHORED) != 0)? ",endanchored" : "",+ ((match_options & PCRE2_NO_JIT) != 0)? ",no_jit" : "",+ ((match_options & PCRE2_NO_UTF_CHECK) != 0)? ",no_utf_check" : "",+ ((match_options & PCRE2_NOTBOL) != 0)? ",notbol" : "",+ ((match_options & PCRE2_NOTEMPTY) != 0)? ",notempty" : "",+ ((match_options & PCRE2_NOTEMPTY_ATSTART) != 0)? ",notempty_atstart" : "",+ ((match_options & PCRE2_NOTEOL) != 0)? ",noteol" : "",+ ((match_options & PCRE2_PARTIAL_HARD) != 0)? ",partial_hard" : "",+ ((match_options & PCRE2_PARTIAL_SOFT) != 0)? ",partial_soft" : "");+#endif++ callout_count = 0;+ errorcode = pcre2_match(code, (PCRE2_SPTR)data, (PCRE2_SIZE)match_size, 0,+ match_options, match_data, match_context);++#ifdef STANDALONE+ if (errorcode >= 0) printf("Match returned %d\n", errorcode); else+ {+ unsigned char buffer[256];+ pcre2_get_error_message(errorcode, buffer, 256);+ printf("Match failed: error %d: %s\n", errorcode, buffer);+ }+#endif++ match_options = 0; /* For second time */+ }++ /* Match with DFA twice, with and without options. */++ match_options = save_match_options & ~PCRE2_NO_JIT; /* Not valid for DFA */++ for (j = 0; j < 2; j++)+ {+#ifdef STANDALONE+ printf("DFA match options %.8x", match_options);+ printf("%s%s%s%s%s%s%s%s%s\n",+ ((match_options & PCRE2_ANCHORED) != 0)? ",anchored" : "",+ ((match_options & PCRE2_ENDANCHORED) != 0)? ",endanchored" : "",+ ((match_options & PCRE2_NO_UTF_CHECK) != 0)? ",no_utf_check" : "",+ ((match_options & PCRE2_NOTBOL) != 0)? ",notbol" : "",+ ((match_options & PCRE2_NOTEMPTY) != 0)? ",notempty" : "",+ ((match_options & PCRE2_NOTEMPTY_ATSTART) != 0)? ",notempty_atstart" : "",+ ((match_options & PCRE2_NOTEOL) != 0)? ",noteol" : "",+ ((match_options & PCRE2_PARTIAL_HARD) != 0)? ",partial_hard" : "",+ ((match_options & PCRE2_PARTIAL_SOFT) != 0)? ",partial_soft" : "");+#endif++ callout_count = 0;+ errorcode = pcre2_dfa_match(code, (PCRE2_SPTR)data,+ (PCRE2_SIZE)match_size, 0, match_options, match_data, match_context,+ dfa_workspace, DFA_WORKSPACE_COUNT);++#ifdef STANDALONE+ if (errorcode >= 0) printf("Match returned %d\n", errorcode); else+ {+ unsigned char buffer[256];+ pcre2_get_error_message(errorcode, buffer, 256);+ printf("Match failed: error %d: %s\n", errorcode, buffer);+ }+#endif++ match_options = 0; /* For second time */+ }++ match_options = save_match_options; /* Reset for the second compile */+ pcre2_code_free(code);+ }++ /* Compilation failed */++ else+ {+ unsigned char buffer[256];+ pcre2_get_error_message(errorcode, buffer, 256);+#ifdef STANDALONE+ printf("Error %d at offset %lu: %s\n", errorcode, erroroffset, buffer);+#else+ if (strstr((const char *)buffer, "internal error") != NULL) abort();+#endif+ }++ compile_options = PCRE2_NEVER_BACKSLASH_C; /* For second time */+ }++if (match_data != NULL) pcre2_match_data_free(match_data);+if (match_context != NULL) pcre2_match_context_free(match_context);++return 0;+}+++/* Optional main program. */++#ifdef STANDALONE+int main(int argc, char **argv)+{+int i;++if (argc < 2)+ {+ printf("** No arguments given\n");+ return 0;+ }++for (i = 1; i < argc; i++)+ {+ size_t filelen;+ size_t readsize;+ unsigned char *buffer;+ FILE *f;++ /* Handle a literal string. Copy to an exact size buffer so that checks for+ overrunning work. */++ if (argv[i][0] == '=')+ {+ readsize = strlen(argv[i]) - 1;+ printf("------ <Literal> ------\n");+ printf("Length = %lu\n", readsize);+ printf("%.*s\n", (int)readsize, argv[i]+1);+ buffer = (unsigned char *)malloc(readsize);+ if (buffer == NULL)+ printf("** Failed to allocate %lu bytes of memory\n", readsize);+ else+ {+ memcpy(buffer, argv[i]+1, readsize);+ LLVMFuzzerTestOneInput(buffer, readsize);+ free(buffer);+ }+ continue;+ }++ /* Handle a string given in a file */++ f = fopen(argv[i], "rb");+ if (f == NULL)+ {+ printf("** Failed to open %s: %s\n", argv[i], strerror(errno));+ continue;+ }++ printf("------ %s ------\n", argv[i]);++ fseek(f, 0, SEEK_END);+ filelen = ftell(f);+ fseek(f, 0, SEEK_SET);++ buffer = (unsigned char *)malloc(filelen);+ if (buffer == NULL)+ {+ printf("** Failed to allocate %lu bytes of memory\n", filelen);+ fclose(f);+ continue;+ }++ readsize = fread(buffer, 1, filelen, f);+ fclose(f);++ if (readsize != filelen)+ printf("** File size is %lu but fread() returned %lu\n", filelen, readsize);+ else+ {+ printf("Length = %lu\n", filelen);+ LLVMFuzzerTestOneInput(buffer, filelen);+ }+ free(buffer);+ }++return 0;+}+#endif /* STANDALONE */++/* End */
+ src/c/pcre2/src/pcre2_internal.h view
@@ -0,0 +1,2004 @@+/*************************************************+* Perl-Compatible Regular Expressions *+*************************************************/++/* PCRE2 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) 2016-2020 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.+-----------------------------------------------------------------------------+*/++#ifndef PCRE2_INTERNAL_H_IDEMPOTENT_GUARD+#define PCRE2_INTERNAL_H_IDEMPOTENT_GUARD++/* We do not support both EBCDIC and Unicode at the same time. The "configure"+script prevents both being selected, but not everybody uses "configure". EBCDIC+is only supported for the 8-bit library, but the check for this has to be later+in this file, because the first part is not width-dependent, and is included by+pcre2test.c with CODE_UNIT_WIDTH == 0. */++#if defined EBCDIC && defined SUPPORT_UNICODE+#error The use of both EBCDIC and SUPPORT_UNICODE is not supported.+#endif++/* Standard C headers */++#include <ctype.h>+#include <limits.h>+#include <stddef.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>++/* Macros to make boolean values more obvious. The #ifndef is to pacify+compiler warnings in environments where these macros are defined elsewhere.+Unfortunately, there is no way to do the same for the typedef. */++typedef int BOOL;+#ifndef FALSE+#define FALSE 0+#define TRUE 1+#endif++/* Valgrind (memcheck) support */++#ifdef SUPPORT_VALGRIND+#include <valgrind/memcheck.h>+#endif++/* -ftrivial-auto-var-init support supports initializing all local variables+to avoid some classes of bug, but this can cause an unacceptable slowdown+for large on-stack arrays in hot functions. This macro lets us annotate+such arrays. */++#ifdef HAVE_ATTRIBUTE_UNINITIALIZED+#define PCRE2_KEEP_UNINITIALIZED __attribute__((uninitialized))+#else+#define PCRE2_KEEP_UNINITIALIZED+#endif++/* Older versions of MSVC lack snprintf(). This define allows for+warning/error-free compilation and testing with MSVC compilers back to at least+MSVC 10/2010. Except for VC6 (which is missing some fundamentals and fails). */++#if defined(_MSC_VER) && (_MSC_VER < 1900)+#define snprintf _snprintf+#endif++/* When compiling a DLL for Windows, the exported symbols have to be declared+using some MS magic. I found some useful information on this web page:+http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the+information there, using __declspec(dllexport) without "extern" we have a+definition; with "extern" we have a declaration. The settings here override the+setting in pcre2.h (which is included below); it defines only PCRE2_EXP_DECL,+which is all that is needed for applications (they just import the symbols). We+use:++ PCRE2_EXP_DECL for declarations+ PCRE2_EXP_DEFN for definitions++The reason for wrapping this in #ifndef PCRE2_EXP_DECL is so that pcre2test,+which is an application, but needs to import this file in order to "peek" at+internals, can #include pcre2.h first to get an application's-eye view.++In principle, people compiling for non-Windows, non-Unix-like (i.e. uncommon,+special-purpose environments) might want to stick other stuff in front of+exported symbols. That's why, in the non-Windows case, we set PCRE2_EXP_DEFN+only if it is not already set. */++#ifndef PCRE2_EXP_DECL+# ifdef _WIN32+# ifndef PCRE2_STATIC+# define PCRE2_EXP_DECL extern __declspec(dllexport)+# define PCRE2_EXP_DEFN __declspec(dllexport)+# else+# define PCRE2_EXP_DECL extern+# define PCRE2_EXP_DEFN+# endif+# else+# ifdef __cplusplus+# define PCRE2_EXP_DECL extern "C"+# else+# define PCRE2_EXP_DECL extern+# endif+# ifndef PCRE2_EXP_DEFN+# define PCRE2_EXP_DEFN PCRE2_EXP_DECL+# endif+# endif+#endif++/* Include the public PCRE2 header and the definitions of UCP character+property values. This must follow the setting of PCRE2_EXP_DECL above. */++#include "pcre2.h"+#include "pcre2_ucp.h"++/* When PCRE2 is compiled as a C++ library, the subject pointer can be replaced+with a custom type. This makes it possible, for example, to allow pcre2_match()+to process subject strings that are discontinuous by using a smart pointer+class. It must always be possible to inspect all of the subject string in+pcre2_match() because of the way it backtracks. */++/* WARNING: This is as yet untested for PCRE2. */++#ifdef CUSTOM_SUBJECT_PTR+#undef PCRE2_SPTR+#define PCRE2_SPTR CUSTOM_SUBJECT_PTR+#endif++/* When checking for integer overflow in pcre2_compile(), we need to handle+large integers. If a 64-bit integer type is available, we can use that.+Otherwise we have to cast to double, which of course requires floating point+arithmetic. Handle this by defining a macro for the appropriate type. */++#if defined INT64_MAX || defined int64_t+#define INT64_OR_DOUBLE int64_t+#else+#define INT64_OR_DOUBLE double+#endif++/* External (in the C sense) functions and tables that are private to the+libraries are always referenced using the PRIV macro. This makes it possible+for pcre2test.c to include some of the source files from the libraries using a+different PRIV definition to avoid name clashes. It also makes it clear in the+code that a non-static object is being referenced. */++#ifndef PRIV+#define PRIV(name) _pcre2_##name+#endif++/* When compiling for use with the Virtual Pascal compiler, these functions+need to have their names changed. PCRE2 must be compiled with the -DVPCOMPAT+option on the command line. */++#ifdef VPCOMPAT+#define strlen(s) _strlen(s)+#define strncmp(s1,s2,m) _strncmp(s1,s2,m)+#define memcmp(s,c,n) _memcmp(s,c,n)+#define memcpy(d,s,n) _memcpy(d,s,n)+#define memmove(d,s,n) _memmove(d,s,n)+#define memset(s,c,n) _memset(s,c,n)+#else /* VPCOMPAT */++/* Otherwise, to cope with SunOS4 and other systems that lack memmove(), define+a macro that calls an emulating function. */++#ifndef HAVE_MEMMOVE+#undef memmove /* Some systems may have a macro */+#define memmove(a, b, c) PRIV(memmove)(a, b, c)+#endif /* not HAVE_MEMMOVE */+#endif /* not VPCOMPAT */++/* This is an unsigned int value that no UTF character can ever have, as+Unicode doesn't go beyond 0x0010ffff. */++#define NOTACHAR 0xffffffff++/* This is the largest valid UTF/Unicode code point. */++#define MAX_UTF_CODE_POINT 0x10ffff++/* Compile-time positive error numbers (all except UTF errors, which are+negative) start at this value. It should probably never be changed, in case+some application is checking for specific numbers. There is a copy of this+#define in pcre2posix.c (which now no longer includes this file). Ideally, a+way of having a single definition should be found, but as the number is+unlikely to change, this is not a pressing issue. The original reason for+having a base other than 0 was to keep the absolute values of compile-time and+run-time error numbers numerically different, but in the event the code does+not rely on this. */++#define COMPILE_ERROR_BASE 100++/* The initial frames vector for remembering backtracking points in+pcre2_match() is allocated on the system stack, of this size (bytes). The size+must be a multiple of sizeof(PCRE2_SPTR) in all environments, so making it a+multiple of 8 is best. Typical frame sizes are a few hundred bytes (it depends+on the number of capturing parentheses) so 20KiB handles quite a few frames. A+larger vector on the heap is obtained for patterns that need more frames. The+maximum size of this can be limited. */++#define START_FRAMES_SIZE 20480++/* Similarly, for DFA matching, an initial internal workspace vector is+allocated on the stack. */++#define DFA_START_RWS_SIZE 30720++/* Define the default BSR convention. */++#ifdef BSR_ANYCRLF+#define BSR_DEFAULT PCRE2_BSR_ANYCRLF+#else+#define BSR_DEFAULT PCRE2_BSR_UNICODE+#endif+++/* ---------------- Basic UTF-8 macros ---------------- */++/* These UTF-8 macros are always defined because they are used in pcre2test for+handling wide characters in 16-bit and 32-bit modes, even if an 8-bit library+is not supported. */++/* Tests whether a UTF-8 code point needs extra bytes to decode. */++#define HASUTF8EXTRALEN(c) ((c) >= 0xc0)++/* The following macros were originally written in the form of loops that used+data from the tables whose names start with PRIV(utf8_table). They were+rewritten by a user so as not to use loops, because in some environments this+gives a significant performance advantage, and it seems never to do any harm.+*/++/* Base macro to pick up the remaining bytes of a UTF-8 character, not+advancing the pointer. */++#define GETUTF8(c, eptr) \+ { \+ if ((c & 0x20u) == 0) \+ c = ((c & 0x1fu) << 6) | (eptr[1] & 0x3fu); \+ else if ((c & 0x10u) == 0) \+ c = ((c & 0x0fu) << 12) | ((eptr[1] & 0x3fu) << 6) | (eptr[2] & 0x3fu); \+ else if ((c & 0x08u) == 0) \+ c = ((c & 0x07u) << 18) | ((eptr[1] & 0x3fu) << 12) | \+ ((eptr[2] & 0x3fu) << 6) | (eptr[3] & 0x3fu); \+ else if ((c & 0x04u) == 0) \+ c = ((c & 0x03u) << 24) | ((eptr[1] & 0x3fu) << 18) | \+ ((eptr[2] & 0x3fu) << 12) | ((eptr[3] & 0x3fu) << 6) | \+ (eptr[4] & 0x3fu); \+ else \+ c = ((c & 0x01u) << 30) | ((eptr[1] & 0x3fu) << 24) | \+ ((eptr[2] & 0x3fu) << 18) | ((eptr[3] & 0x3fu) << 12) | \+ ((eptr[4] & 0x3fu) << 6) | (eptr[5] & 0x3fu); \+ }++/* Base macro to pick up the remaining bytes of a UTF-8 character, advancing+the pointer. */++#define GETUTF8INC(c, eptr) \+ { \+ if ((c & 0x20u) == 0) \+ c = ((c & 0x1fu) << 6) | (*eptr++ & 0x3fu); \+ else if ((c & 0x10u) == 0) \+ { \+ c = ((c & 0x0fu) << 12) | ((*eptr & 0x3fu) << 6) | (eptr[1] & 0x3fu); \+ eptr += 2; \+ } \+ else if ((c & 0x08u) == 0) \+ { \+ c = ((c & 0x07u) << 18) | ((*eptr & 0x3fu) << 12) | \+ ((eptr[1] & 0x3fu) << 6) | (eptr[2] & 0x3fu); \+ eptr += 3; \+ } \+ else if ((c & 0x04u) == 0) \+ { \+ c = ((c & 0x03u) << 24) | ((*eptr & 0x3fu) << 18) | \+ ((eptr[1] & 0x3fu) << 12) | ((eptr[2] & 0x3fu) << 6) | \+ (eptr[3] & 0x3fu); \+ eptr += 4; \+ } \+ else \+ { \+ c = ((c & 0x01u) << 30) | ((*eptr & 0x3fu) << 24) | \+ ((eptr[1] & 0x3fu) << 18) | ((eptr[2] & 0x3fu) << 12) | \+ ((eptr[3] & 0x3fu) << 6) | (eptr[4] & 0x3fu); \+ eptr += 5; \+ } \+ }++/* Base macro to pick up the remaining bytes of a UTF-8 character, not+advancing the pointer, incrementing the length. */++#define GETUTF8LEN(c, eptr, len) \+ { \+ if ((c & 0x20u) == 0) \+ { \+ c = ((c & 0x1fu) << 6) | (eptr[1] & 0x3fu); \+ len++; \+ } \+ else if ((c & 0x10u) == 0) \+ { \+ c = ((c & 0x0fu) << 12) | ((eptr[1] & 0x3fu) << 6) | (eptr[2] & 0x3fu); \+ len += 2; \+ } \+ else if ((c & 0x08u) == 0) \+ {\+ c = ((c & 0x07u) << 18) | ((eptr[1] & 0x3fu) << 12) | \+ ((eptr[2] & 0x3fu) << 6) | (eptr[3] & 0x3fu); \+ len += 3; \+ } \+ else if ((c & 0x04u) == 0) \+ { \+ c = ((c & 0x03u) << 24) | ((eptr[1] & 0x3fu) << 18) | \+ ((eptr[2] & 0x3fu) << 12) | ((eptr[3] & 0x3fu) << 6) | \+ (eptr[4] & 0x3fu); \+ len += 4; \+ } \+ else \+ {\+ c = ((c & 0x01u) << 30) | ((eptr[1] & 0x3fu) << 24) | \+ ((eptr[2] & 0x3fu) << 18) | ((eptr[3] & 0x3fu) << 12) | \+ ((eptr[4] & 0x3fu) << 6) | (eptr[5] & 0x3fu); \+ len += 5; \+ } \+ }++/* --------------- Whitespace macros ---------------- */++/* Tests for Unicode horizontal and vertical whitespace characters must check a+number of different values. Using a switch statement for this generates the+fastest code (no loop, no memory access), and there are several places in the+interpreter code where this happens. In order to ensure that all the case lists+remain in step, we use macros so that there is only one place where the lists+are defined.++These values are also required as lists in pcre2_compile.c when processing \h,+\H, \v and \V in a character class. The lists are defined in pcre2_tables.c,+but macros that define the values are here so that all the definitions are+together. The lists must be in ascending character order, terminated by+NOTACHAR (which is 0xffffffff).++Any changes should ensure that the various macros are kept in step with each+other. NOTE: The values also appear in pcre2_jit_compile.c. */++/* -------------- ASCII/Unicode environments -------------- */++#ifndef EBCDIC++/* Character U+180E (Mongolian Vowel Separator) is not included in the list of+spaces in the Unicode file PropList.txt, and Perl does not recognize it as a+space. However, in many other sources it is listed as a space and has been in+PCRE (both APIs) for a long time. */++#define HSPACE_LIST \+ CHAR_HT, CHAR_SPACE, CHAR_NBSP, \+ 0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \+ 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \+ NOTACHAR++#define HSPACE_MULTIBYTE_CASES \+ case 0x1680: /* OGHAM SPACE MARK */ \+ case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ \+ case 0x2000: /* EN QUAD */ \+ case 0x2001: /* EM QUAD */ \+ case 0x2002: /* EN SPACE */ \+ case 0x2003: /* EM SPACE */ \+ case 0x2004: /* THREE-PER-EM SPACE */ \+ case 0x2005: /* FOUR-PER-EM SPACE */ \+ case 0x2006: /* SIX-PER-EM SPACE */ \+ case 0x2007: /* FIGURE SPACE */ \+ case 0x2008: /* PUNCTUATION SPACE */ \+ case 0x2009: /* THIN SPACE */ \+ case 0x200A: /* HAIR SPACE */ \+ case 0x202f: /* NARROW NO-BREAK SPACE */ \+ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ \+ case 0x3000 /* IDEOGRAPHIC SPACE */++#define HSPACE_BYTE_CASES \+ case CHAR_HT: \+ case CHAR_SPACE: \+ case CHAR_NBSP++#define HSPACE_CASES \+ HSPACE_BYTE_CASES: \+ HSPACE_MULTIBYTE_CASES++#define VSPACE_LIST \+ CHAR_LF, CHAR_VT, CHAR_FF, CHAR_CR, CHAR_NEL, 0x2028, 0x2029, NOTACHAR++#define VSPACE_MULTIBYTE_CASES \+ case 0x2028: /* LINE SEPARATOR */ \+ case 0x2029 /* PARAGRAPH SEPARATOR */++#define VSPACE_BYTE_CASES \+ case CHAR_LF: \+ case CHAR_VT: \+ case CHAR_FF: \+ case CHAR_CR: \+ case CHAR_NEL++#define VSPACE_CASES \+ VSPACE_BYTE_CASES: \+ VSPACE_MULTIBYTE_CASES++/* -------------- EBCDIC environments -------------- */++#else+#define HSPACE_LIST CHAR_HT, CHAR_SPACE, CHAR_NBSP, NOTACHAR++#define HSPACE_BYTE_CASES \+ case CHAR_HT: \+ case CHAR_SPACE: \+ case CHAR_NBSP++#define HSPACE_CASES HSPACE_BYTE_CASES++#ifdef EBCDIC_NL25+#define VSPACE_LIST \+ CHAR_VT, CHAR_FF, CHAR_CR, CHAR_NEL, CHAR_LF, NOTACHAR+#else+#define VSPACE_LIST \+ CHAR_VT, CHAR_FF, CHAR_CR, CHAR_LF, CHAR_NEL, NOTACHAR+#endif++#define VSPACE_BYTE_CASES \+ case CHAR_LF: \+ case CHAR_VT: \+ case CHAR_FF: \+ case CHAR_CR: \+ case CHAR_NEL++#define VSPACE_CASES VSPACE_BYTE_CASES+#endif /* EBCDIC */++/* -------------- End of whitespace macros -------------- */+++/* PCRE2 is able to support several different kinds of newline (CR, LF, CRLF,+"any" and "anycrlf" at present). The following macros are used to package up+testing for newlines. NLBLOCK, PSSTART, and PSEND are defined in the various+modules to indicate in which datablock the parameters exist, and what the+start/end of string field names are. */++#define NLTYPE_FIXED 0 /* Newline is a fixed length string */+#define NLTYPE_ANY 1 /* Newline is any Unicode line ending */+#define NLTYPE_ANYCRLF 2 /* Newline is CR, LF, or CRLF */++/* This macro checks for a newline at the given position */++#define IS_NEWLINE(p) \+ ((NLBLOCK->nltype != NLTYPE_FIXED)? \+ ((p) < NLBLOCK->PSEND && \+ PRIV(is_newline)((p), NLBLOCK->nltype, NLBLOCK->PSEND, \+ &(NLBLOCK->nllen), utf)) \+ : \+ ((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \+ UCHAR21TEST(p) == NLBLOCK->nl[0] && \+ (NLBLOCK->nllen == 1 || UCHAR21TEST(p+1) == NLBLOCK->nl[1]) \+ ) \+ )++/* This macro checks for a newline immediately preceding the given position */++#define WAS_NEWLINE(p) \+ ((NLBLOCK->nltype != NLTYPE_FIXED)? \+ ((p) > NLBLOCK->PSSTART && \+ PRIV(was_newline)((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \+ &(NLBLOCK->nllen), utf)) \+ : \+ ((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \+ UCHAR21TEST(p - NLBLOCK->nllen) == NLBLOCK->nl[0] && \+ (NLBLOCK->nllen == 1 || UCHAR21TEST(p - NLBLOCK->nllen + 1) == NLBLOCK->nl[1]) \+ ) \+ )++/* Private flags containing information about the compiled pattern. The first+three must not be changed, because whichever is set is actually the number of+bytes in a code unit in that mode. */++#define PCRE2_MODE8 0x00000001 /* compiled in 8 bit mode */+#define PCRE2_MODE16 0x00000002 /* compiled in 16 bit mode */+#define PCRE2_MODE32 0x00000004 /* compiled in 32 bit mode */+#define PCRE2_FIRSTSET 0x00000010 /* first_code unit is set */+#define PCRE2_FIRSTCASELESS 0x00000020 /* caseless first code unit */+#define PCRE2_FIRSTMAPSET 0x00000040 /* bitmap of first code units is set */+#define PCRE2_LASTSET 0x00000080 /* last code unit is set */+#define PCRE2_LASTCASELESS 0x00000100 /* caseless last code unit */+#define PCRE2_STARTLINE 0x00000200 /* start after \n for multiline */+#define PCRE2_JCHANGED 0x00000400 /* j option used in pattern */+#define PCRE2_HASCRORLF 0x00000800 /* explicit \r or \n in pattern */+#define PCRE2_HASTHEN 0x00001000 /* pattern contains (*THEN) */+#define PCRE2_MATCH_EMPTY 0x00002000 /* pattern can match empty string */+#define PCRE2_BSR_SET 0x00004000 /* BSR was set in the pattern */+#define PCRE2_NL_SET 0x00008000 /* newline was set in the pattern */+#define PCRE2_NOTEMPTY_SET 0x00010000 /* (*NOTEMPTY) used ) keep */+#define PCRE2_NE_ATST_SET 0x00020000 /* (*NOTEMPTY_ATSTART) used) together */+#define PCRE2_DEREF_TABLES 0x00040000 /* release character tables */+#define PCRE2_NOJIT 0x00080000 /* (*NOJIT) used */+#define PCRE2_HASBKPORX 0x00100000 /* contains \P, \p, or \X */+#define PCRE2_DUPCAPUSED 0x00200000 /* contains (?| */+#define PCRE2_HASBKC 0x00400000 /* contains \C */+#define PCRE2_HASACCEPT 0x00800000 /* contains (*ACCEPT) */++#define PCRE2_MODE_MASK (PCRE2_MODE8 | PCRE2_MODE16 | PCRE2_MODE32)++/* Values for the matchedby field in a match data block. */++enum { PCRE2_MATCHEDBY_INTERPRETER, /* pcre2_match() */+ PCRE2_MATCHEDBY_DFA_INTERPRETER, /* pcre2_dfa_match() */+ PCRE2_MATCHEDBY_JIT }; /* pcre2_jit_match() */++/* Values for the flags field in a match data block. */++#define PCRE2_MD_COPIED_SUBJECT 0x01u++/* Magic number to provide a small check against being handed junk. */++#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */++/* The maximum remaining length of subject we are prepared to search for a+req_unit match from an anchored pattern. In 8-bit mode, memchr() is used and is+much faster than the search loop that has to be used in 16-bit and 32-bit+modes. */++#if PCRE2_CODE_UNIT_WIDTH == 8+#define REQ_CU_MAX 5000+#else+#define REQ_CU_MAX 2000+#endif++/* Offsets for the bitmap tables in the cbits set of tables. Each table+contains a set of bits for a class map. Some classes are built by combining+these tables. */++#define cbit_space 0 /* [:space:] or \s */+#define cbit_xdigit 32 /* [:xdigit:] */+#define cbit_digit 64 /* [:digit:] or \d */+#define cbit_upper 96 /* [:upper:] */+#define cbit_lower 128 /* [:lower:] */+#define cbit_word 160 /* [:word:] or \w */+#define cbit_graph 192 /* [:graph:] */+#define cbit_print 224 /* [:print:] */+#define cbit_punct 256 /* [:punct:] */+#define cbit_cntrl 288 /* [:cntrl:] */+#define cbit_length 320 /* Length of the cbits table */++/* Bit definitions for entries in the ctypes table. Do not change these values+without checking pcre2_jit_compile.c, which has an assertion to ensure that+ctype_word has the value 16. */++#define ctype_space 0x01+#define ctype_letter 0x02+#define ctype_lcletter 0x04+#define ctype_digit 0x08+#define ctype_word 0x10 /* alphanumeric or '_' */++/* Offsets of the various tables from the base tables pointer, and+total length of the tables. */++#define lcc_offset 0 /* Lower case */+#define fcc_offset 256 /* Flip case */+#define cbits_offset 512 /* Character classes */+#define ctypes_offset (cbits_offset + cbit_length) /* Character types */+#define TABLES_LENGTH (ctypes_offset + 256)+++/* -------------------- Character and string names ------------------------ */++/* If PCRE2 is to support UTF-8 on EBCDIC platforms, we cannot use normal+character constants like '*' because the compiler would emit their EBCDIC code,+which is different from their ASCII/UTF-8 code. Instead we define macros for+the characters so that they always use the ASCII/UTF-8 code when UTF-8 support+is enabled. When UTF-8 support is not enabled, the definitions use character+literals. Both character and string versions of each character are needed, and+there are some longer strings as well.++This means that, on EBCDIC platforms, the PCRE2 library can handle either+EBCDIC, or UTF-8, but not both. To support both in the same compiled library+would need different lookups depending on whether PCRE2_UTF was set or not.+This would make it impossible to use characters in switch/case statements,+which would reduce performance. For a theoretical use (which nobody has asked+for) in a minority area (EBCDIC platforms), this is not sensible. Any+application that did need both could compile two versions of the library, using+macros to give the functions distinct names. */++#ifndef SUPPORT_UNICODE++/* UTF-8 support is not enabled; use the platform-dependent character literals+so that PCRE2 works in both ASCII and EBCDIC environments, but only in non-UTF+mode. Newline characters are problematic in EBCDIC. Though it has CR and LF+characters, a common practice has been to use its NL (0x15) character as the+line terminator in C-like processing environments. However, sometimes the LF+(0x25) character is used instead, according to this Unicode document:++http://unicode.org/standard/reports/tr13/tr13-5.html++PCRE2 defaults EBCDIC NL to 0x15, but has a build-time option to select 0x25+instead. Whichever is *not* chosen is defined as NEL.++In both ASCII and EBCDIC environments, CHAR_NL and CHAR_LF are synonyms for the+same code point. */++#ifdef EBCDIC++#ifndef EBCDIC_NL25+#define CHAR_NL '\x15'+#define CHAR_NEL '\x25'+#define STR_NL "\x15"+#define STR_NEL "\x25"+#else+#define CHAR_NL '\x25'+#define CHAR_NEL '\x15'+#define STR_NL "\x25"+#define STR_NEL "\x15"+#endif++#define CHAR_LF CHAR_NL+#define STR_LF STR_NL++#define CHAR_ESC '\047'+#define CHAR_DEL '\007'+#define CHAR_NBSP ((unsigned char)'\x41')+#define STR_ESC "\047"+#define STR_DEL "\007"++#else /* Not EBCDIC */++/* In ASCII/Unicode, linefeed is '\n' and we equate this to NL for+compatibility. NEL is the Unicode newline character; make sure it is+a positive value. */++#define CHAR_LF '\n'+#define CHAR_NL CHAR_LF+#define CHAR_NEL ((unsigned char)'\x85')+#define CHAR_ESC '\033'+#define CHAR_DEL '\177'+#define CHAR_NBSP ((unsigned char)'\xa0')++#define STR_LF "\n"+#define STR_NL STR_LF+#define STR_NEL "\x85"+#define STR_ESC "\033"+#define STR_DEL "\177"++#endif /* EBCDIC */++/* The remaining definitions work in both environments. */++#define CHAR_NUL '\0'+#define CHAR_HT '\t'+#define CHAR_VT '\v'+#define CHAR_FF '\f'+#define CHAR_CR '\r'+#define CHAR_BS '\b'+#define CHAR_BEL '\a'++#define CHAR_SPACE ' '+#define CHAR_EXCLAMATION_MARK '!'+#define CHAR_QUOTATION_MARK '"'+#define CHAR_NUMBER_SIGN '#'+#define CHAR_DOLLAR_SIGN '$'+#define CHAR_PERCENT_SIGN '%'+#define CHAR_AMPERSAND '&'+#define CHAR_APOSTROPHE '\''+#define CHAR_LEFT_PARENTHESIS '('+#define CHAR_RIGHT_PARENTHESIS ')'+#define CHAR_ASTERISK '*'+#define CHAR_PLUS '+'+#define CHAR_COMMA ','+#define CHAR_MINUS '-'+#define CHAR_DOT '.'+#define CHAR_SLASH '/'+#define CHAR_0 '0'+#define CHAR_1 '1'+#define CHAR_2 '2'+#define CHAR_3 '3'+#define CHAR_4 '4'+#define CHAR_5 '5'+#define CHAR_6 '6'+#define CHAR_7 '7'+#define CHAR_8 '8'+#define CHAR_9 '9'+#define CHAR_COLON ':'+#define CHAR_SEMICOLON ';'+#define CHAR_LESS_THAN_SIGN '<'+#define CHAR_EQUALS_SIGN '='+#define CHAR_GREATER_THAN_SIGN '>'+#define CHAR_QUESTION_MARK '?'+#define CHAR_COMMERCIAL_AT '@'+#define CHAR_A 'A'+#define CHAR_B 'B'+#define CHAR_C 'C'+#define CHAR_D 'D'+#define CHAR_E 'E'+#define CHAR_F 'F'+#define CHAR_G 'G'+#define CHAR_H 'H'+#define CHAR_I 'I'+#define CHAR_J 'J'+#define CHAR_K 'K'+#define CHAR_L 'L'+#define CHAR_M 'M'+#define CHAR_N 'N'+#define CHAR_O 'O'+#define CHAR_P 'P'+#define CHAR_Q 'Q'+#define CHAR_R 'R'+#define CHAR_S 'S'+#define CHAR_T 'T'+#define CHAR_U 'U'+#define CHAR_V 'V'+#define CHAR_W 'W'+#define CHAR_X 'X'+#define CHAR_Y 'Y'+#define CHAR_Z 'Z'+#define CHAR_LEFT_SQUARE_BRACKET '['+#define CHAR_BACKSLASH '\\'+#define CHAR_RIGHT_SQUARE_BRACKET ']'+#define CHAR_CIRCUMFLEX_ACCENT '^'+#define CHAR_UNDERSCORE '_'+#define CHAR_GRAVE_ACCENT '`'+#define CHAR_a 'a'+#define CHAR_b 'b'+#define CHAR_c 'c'+#define CHAR_d 'd'+#define CHAR_e 'e'+#define CHAR_f 'f'+#define CHAR_g 'g'+#define CHAR_h 'h'+#define CHAR_i 'i'+#define CHAR_j 'j'+#define CHAR_k 'k'+#define CHAR_l 'l'+#define CHAR_m 'm'+#define CHAR_n 'n'+#define CHAR_o 'o'+#define CHAR_p 'p'+#define CHAR_q 'q'+#define CHAR_r 'r'+#define CHAR_s 's'+#define CHAR_t 't'+#define CHAR_u 'u'+#define CHAR_v 'v'+#define CHAR_w 'w'+#define CHAR_x 'x'+#define CHAR_y 'y'+#define CHAR_z 'z'+#define CHAR_LEFT_CURLY_BRACKET '{'+#define CHAR_VERTICAL_LINE '|'+#define CHAR_RIGHT_CURLY_BRACKET '}'+#define CHAR_TILDE '~'++#define STR_HT "\t"+#define STR_VT "\v"+#define STR_FF "\f"+#define STR_CR "\r"+#define STR_BS "\b"+#define STR_BEL "\a"++#define STR_SPACE " "+#define STR_EXCLAMATION_MARK "!"+#define STR_QUOTATION_MARK "\""+#define STR_NUMBER_SIGN "#"+#define STR_DOLLAR_SIGN "$"+#define STR_PERCENT_SIGN "%"+#define STR_AMPERSAND "&"+#define STR_APOSTROPHE "'"+#define STR_LEFT_PARENTHESIS "("+#define STR_RIGHT_PARENTHESIS ")"+#define STR_ASTERISK "*"+#define STR_PLUS "+"+#define STR_COMMA ","+#define STR_MINUS "-"+#define STR_DOT "."+#define STR_SLASH "/"+#define STR_0 "0"+#define STR_1 "1"+#define STR_2 "2"+#define STR_3 "3"+#define STR_4 "4"+#define STR_5 "5"+#define STR_6 "6"+#define STR_7 "7"+#define STR_8 "8"+#define STR_9 "9"+#define STR_COLON ":"+#define STR_SEMICOLON ";"+#define STR_LESS_THAN_SIGN "<"+#define STR_EQUALS_SIGN "="+#define STR_GREATER_THAN_SIGN ">"+#define STR_QUESTION_MARK "?"+#define STR_COMMERCIAL_AT "@"+#define STR_A "A"+#define STR_B "B"+#define STR_C "C"+#define STR_D "D"+#define STR_E "E"+#define STR_F "F"+#define STR_G "G"+#define STR_H "H"+#define STR_I "I"+#define STR_J "J"+#define STR_K "K"+#define STR_L "L"+#define STR_M "M"+#define STR_N "N"+#define STR_O "O"+#define STR_P "P"+#define STR_Q "Q"+#define STR_R "R"+#define STR_S "S"+#define STR_T "T"+#define STR_U "U"+#define STR_V "V"+#define STR_W "W"+#define STR_X "X"+#define STR_Y "Y"+#define STR_Z "Z"+#define STR_LEFT_SQUARE_BRACKET "["+#define STR_BACKSLASH "\\"+#define STR_RIGHT_SQUARE_BRACKET "]"+#define STR_CIRCUMFLEX_ACCENT "^"+#define STR_UNDERSCORE "_"+#define STR_GRAVE_ACCENT "`"+#define STR_a "a"+#define STR_b "b"+#define STR_c "c"+#define STR_d "d"+#define STR_e "e"+#define STR_f "f"+#define STR_g "g"+#define STR_h "h"+#define STR_i "i"+#define STR_j "j"+#define STR_k "k"+#define STR_l "l"+#define STR_m "m"+#define STR_n "n"+#define STR_o "o"+#define STR_p "p"+#define STR_q "q"+#define STR_r "r"+#define STR_s "s"+#define STR_t "t"+#define STR_u "u"+#define STR_v "v"+#define STR_w "w"+#define STR_x "x"+#define STR_y "y"+#define STR_z "z"+#define STR_LEFT_CURLY_BRACKET "{"+#define STR_VERTICAL_LINE "|"+#define STR_RIGHT_CURLY_BRACKET "}"+#define STR_TILDE "~"++#define STRING_ACCEPT0 "ACCEPT\0"+#define STRING_COMMIT0 "COMMIT\0"+#define STRING_F0 "F\0"+#define STRING_FAIL0 "FAIL\0"+#define STRING_MARK0 "MARK\0"+#define STRING_PRUNE0 "PRUNE\0"+#define STRING_SKIP0 "SKIP\0"+#define STRING_THEN "THEN"++#define STRING_atomic0 "atomic\0"+#define STRING_pla0 "pla\0"+#define STRING_plb0 "plb\0"+#define STRING_napla0 "napla\0"+#define STRING_naplb0 "naplb\0"+#define STRING_nla0 "nla\0"+#define STRING_nlb0 "nlb\0"+#define STRING_sr0 "sr\0"+#define STRING_asr0 "asr\0"+#define STRING_positive_lookahead0 "positive_lookahead\0"+#define STRING_positive_lookbehind0 "positive_lookbehind\0"+#define STRING_non_atomic_positive_lookahead0 "non_atomic_positive_lookahead\0"+#define STRING_non_atomic_positive_lookbehind0 "non_atomic_positive_lookbehind\0"+#define STRING_negative_lookahead0 "negative_lookahead\0"+#define STRING_negative_lookbehind0 "negative_lookbehind\0"+#define STRING_script_run0 "script_run\0"+#define STRING_atomic_script_run "atomic_script_run"++#define STRING_alpha0 "alpha\0"+#define STRING_lower0 "lower\0"+#define STRING_upper0 "upper\0"+#define STRING_alnum0 "alnum\0"+#define STRING_ascii0 "ascii\0"+#define STRING_blank0 "blank\0"+#define STRING_cntrl0 "cntrl\0"+#define STRING_digit0 "digit\0"+#define STRING_graph0 "graph\0"+#define STRING_print0 "print\0"+#define STRING_punct0 "punct\0"+#define STRING_space0 "space\0"+#define STRING_word0 "word\0"+#define STRING_xdigit "xdigit"++#define STRING_DEFINE "DEFINE"+#define STRING_VERSION "VERSION"+#define STRING_WEIRD_STARTWORD "[:<:]]"+#define STRING_WEIRD_ENDWORD "[:>:]]"++#define STRING_CR_RIGHTPAR "CR)"+#define STRING_LF_RIGHTPAR "LF)"+#define STRING_CRLF_RIGHTPAR "CRLF)"+#define STRING_ANY_RIGHTPAR "ANY)"+#define STRING_ANYCRLF_RIGHTPAR "ANYCRLF)"+#define STRING_NUL_RIGHTPAR "NUL)"+#define STRING_BSR_ANYCRLF_RIGHTPAR "BSR_ANYCRLF)"+#define STRING_BSR_UNICODE_RIGHTPAR "BSR_UNICODE)"+#define STRING_UTF8_RIGHTPAR "UTF8)"+#define STRING_UTF16_RIGHTPAR "UTF16)"+#define STRING_UTF32_RIGHTPAR "UTF32)"+#define STRING_UTF_RIGHTPAR "UTF)"+#define STRING_UCP_RIGHTPAR "UCP)"+#define STRING_NO_AUTO_POSSESS_RIGHTPAR "NO_AUTO_POSSESS)"+#define STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR "NO_DOTSTAR_ANCHOR)"+#define STRING_NO_JIT_RIGHTPAR "NO_JIT)"+#define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)"+#define STRING_NOTEMPTY_RIGHTPAR "NOTEMPTY)"+#define STRING_NOTEMPTY_ATSTART_RIGHTPAR "NOTEMPTY_ATSTART)"+#define STRING_LIMIT_HEAP_EQ "LIMIT_HEAP="+#define STRING_LIMIT_MATCH_EQ "LIMIT_MATCH="+#define STRING_LIMIT_DEPTH_EQ "LIMIT_DEPTH="+#define STRING_LIMIT_RECURSION_EQ "LIMIT_RECURSION="+#define STRING_MARK "MARK"++#else /* SUPPORT_UNICODE */++/* UTF-8 support is enabled; always use UTF-8 (=ASCII) character codes. This+works in both modes non-EBCDIC platforms, and on EBCDIC platforms in UTF-8 mode+only. */++#define CHAR_HT '\011'+#define CHAR_VT '\013'+#define CHAR_FF '\014'+#define CHAR_CR '\015'+#define CHAR_LF '\012'+#define CHAR_NL CHAR_LF+#define CHAR_NEL ((unsigned char)'\x85')+#define CHAR_BS '\010'+#define CHAR_BEL '\007'+#define CHAR_ESC '\033'+#define CHAR_DEL '\177'++#define CHAR_NUL '\0'+#define CHAR_SPACE '\040'+#define CHAR_EXCLAMATION_MARK '\041'+#define CHAR_QUOTATION_MARK '\042'+#define CHAR_NUMBER_SIGN '\043'+#define CHAR_DOLLAR_SIGN '\044'+#define CHAR_PERCENT_SIGN '\045'+#define CHAR_AMPERSAND '\046'+#define CHAR_APOSTROPHE '\047'+#define CHAR_LEFT_PARENTHESIS '\050'+#define CHAR_RIGHT_PARENTHESIS '\051'+#define CHAR_ASTERISK '\052'+#define CHAR_PLUS '\053'+#define CHAR_COMMA '\054'+#define CHAR_MINUS '\055'+#define CHAR_DOT '\056'+#define CHAR_SLASH '\057'+#define CHAR_0 '\060'+#define CHAR_1 '\061'+#define CHAR_2 '\062'+#define CHAR_3 '\063'+#define CHAR_4 '\064'+#define CHAR_5 '\065'+#define CHAR_6 '\066'+#define CHAR_7 '\067'+#define CHAR_8 '\070'+#define CHAR_9 '\071'+#define CHAR_COLON '\072'+#define CHAR_SEMICOLON '\073'+#define CHAR_LESS_THAN_SIGN '\074'+#define CHAR_EQUALS_SIGN '\075'+#define CHAR_GREATER_THAN_SIGN '\076'+#define CHAR_QUESTION_MARK '\077'+#define CHAR_COMMERCIAL_AT '\100'+#define CHAR_A '\101'+#define CHAR_B '\102'+#define CHAR_C '\103'+#define CHAR_D '\104'+#define CHAR_E '\105'+#define CHAR_F '\106'+#define CHAR_G '\107'+#define CHAR_H '\110'+#define CHAR_I '\111'+#define CHAR_J '\112'+#define CHAR_K '\113'+#define CHAR_L '\114'+#define CHAR_M '\115'+#define CHAR_N '\116'+#define CHAR_O '\117'+#define CHAR_P '\120'+#define CHAR_Q '\121'+#define CHAR_R '\122'+#define CHAR_S '\123'+#define CHAR_T '\124'+#define CHAR_U '\125'+#define CHAR_V '\126'+#define CHAR_W '\127'+#define CHAR_X '\130'+#define CHAR_Y '\131'+#define CHAR_Z '\132'+#define CHAR_LEFT_SQUARE_BRACKET '\133'+#define CHAR_BACKSLASH '\134'+#define CHAR_RIGHT_SQUARE_BRACKET '\135'+#define CHAR_CIRCUMFLEX_ACCENT '\136'+#define CHAR_UNDERSCORE '\137'+#define CHAR_GRAVE_ACCENT '\140'+#define CHAR_a '\141'+#define CHAR_b '\142'+#define CHAR_c '\143'+#define CHAR_d '\144'+#define CHAR_e '\145'+#define CHAR_f '\146'+#define CHAR_g '\147'+#define CHAR_h '\150'+#define CHAR_i '\151'+#define CHAR_j '\152'+#define CHAR_k '\153'+#define CHAR_l '\154'+#define CHAR_m '\155'+#define CHAR_n '\156'+#define CHAR_o '\157'+#define CHAR_p '\160'+#define CHAR_q '\161'+#define CHAR_r '\162'+#define CHAR_s '\163'+#define CHAR_t '\164'+#define CHAR_u '\165'+#define CHAR_v '\166'+#define CHAR_w '\167'+#define CHAR_x '\170'+#define CHAR_y '\171'+#define CHAR_z '\172'+#define CHAR_LEFT_CURLY_BRACKET '\173'+#define CHAR_VERTICAL_LINE '\174'+#define CHAR_RIGHT_CURLY_BRACKET '\175'+#define CHAR_TILDE '\176'+#define CHAR_NBSP ((unsigned char)'\xa0')++#define STR_HT "\011"+#define STR_VT "\013"+#define STR_FF "\014"+#define STR_CR "\015"+#define STR_NL "\012"+#define STR_BS "\010"+#define STR_BEL "\007"+#define STR_ESC "\033"+#define STR_DEL "\177"++#define STR_SPACE "\040"+#define STR_EXCLAMATION_MARK "\041"+#define STR_QUOTATION_MARK "\042"+#define STR_NUMBER_SIGN "\043"+#define STR_DOLLAR_SIGN "\044"+#define STR_PERCENT_SIGN "\045"+#define STR_AMPERSAND "\046"+#define STR_APOSTROPHE "\047"+#define STR_LEFT_PARENTHESIS "\050"+#define STR_RIGHT_PARENTHESIS "\051"+#define STR_ASTERISK "\052"+#define STR_PLUS "\053"+#define STR_COMMA "\054"+#define STR_MINUS "\055"+#define STR_DOT "\056"+#define STR_SLASH "\057"+#define STR_0 "\060"+#define STR_1 "\061"+#define STR_2 "\062"+#define STR_3 "\063"+#define STR_4 "\064"+#define STR_5 "\065"+#define STR_6 "\066"+#define STR_7 "\067"+#define STR_8 "\070"+#define STR_9 "\071"+#define STR_COLON "\072"+#define STR_SEMICOLON "\073"+#define STR_LESS_THAN_SIGN "\074"+#define STR_EQUALS_SIGN "\075"+#define STR_GREATER_THAN_SIGN "\076"+#define STR_QUESTION_MARK "\077"+#define STR_COMMERCIAL_AT "\100"+#define STR_A "\101"+#define STR_B "\102"+#define STR_C "\103"+#define STR_D "\104"+#define STR_E "\105"+#define STR_F "\106"+#define STR_G "\107"+#define STR_H "\110"+#define STR_I "\111"+#define STR_J "\112"+#define STR_K "\113"+#define STR_L "\114"+#define STR_M "\115"+#define STR_N "\116"+#define STR_O "\117"+#define STR_P "\120"+#define STR_Q "\121"+#define STR_R "\122"+#define STR_S "\123"+#define STR_T "\124"+#define STR_U "\125"+#define STR_V "\126"+#define STR_W "\127"+#define STR_X "\130"+#define STR_Y "\131"+#define STR_Z "\132"+#define STR_LEFT_SQUARE_BRACKET "\133"+#define STR_BACKSLASH "\134"+#define STR_RIGHT_SQUARE_BRACKET "\135"+#define STR_CIRCUMFLEX_ACCENT "\136"+#define STR_UNDERSCORE "\137"+#define STR_GRAVE_ACCENT "\140"+#define STR_a "\141"+#define STR_b "\142"+#define STR_c "\143"+#define STR_d "\144"+#define STR_e "\145"+#define STR_f "\146"+#define STR_g "\147"+#define STR_h "\150"+#define STR_i "\151"+#define STR_j "\152"+#define STR_k "\153"+#define STR_l "\154"+#define STR_m "\155"+#define STR_n "\156"+#define STR_o "\157"+#define STR_p "\160"+#define STR_q "\161"+#define STR_r "\162"+#define STR_s "\163"+#define STR_t "\164"+#define STR_u "\165"+#define STR_v "\166"+#define STR_w "\167"+#define STR_x "\170"+#define STR_y "\171"+#define STR_z "\172"+#define STR_LEFT_CURLY_BRACKET "\173"+#define STR_VERTICAL_LINE "\174"+#define STR_RIGHT_CURLY_BRACKET "\175"+#define STR_TILDE "\176"++#define STRING_ACCEPT0 STR_A STR_C STR_C STR_E STR_P STR_T "\0"+#define STRING_COMMIT0 STR_C STR_O STR_M STR_M STR_I STR_T "\0"+#define STRING_F0 STR_F "\0"+#define STRING_FAIL0 STR_F STR_A STR_I STR_L "\0"+#define STRING_MARK0 STR_M STR_A STR_R STR_K "\0"+#define STRING_PRUNE0 STR_P STR_R STR_U STR_N STR_E "\0"+#define STRING_SKIP0 STR_S STR_K STR_I STR_P "\0"+#define STRING_THEN STR_T STR_H STR_E STR_N++#define STRING_atomic0 STR_a STR_t STR_o STR_m STR_i STR_c "\0"+#define STRING_pla0 STR_p STR_l STR_a "\0"+#define STRING_plb0 STR_p STR_l STR_b "\0"+#define STRING_napla0 STR_n STR_a STR_p STR_l STR_a "\0"+#define STRING_naplb0 STR_n STR_a STR_p STR_l STR_b "\0"+#define STRING_nla0 STR_n STR_l STR_a "\0"+#define STRING_nlb0 STR_n STR_l STR_b "\0"+#define STRING_sr0 STR_s STR_r "\0"+#define STRING_asr0 STR_a STR_s STR_r "\0"+#define STRING_positive_lookahead0 STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"+#define STRING_positive_lookbehind0 STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0"+#define STRING_non_atomic_positive_lookahead0 STR_n STR_o STR_n STR_UNDERSCORE STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"+#define STRING_non_atomic_positive_lookbehind0 STR_n STR_o STR_n STR_UNDERSCORE STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0"+#define STRING_negative_lookahead0 STR_n STR_e STR_g STR_a STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"+#define STRING_negative_lookbehind0 STR_n STR_e STR_g STR_a STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0"+#define STRING_script_run0 STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n "\0"+#define STRING_atomic_script_run STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n++#define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0"+#define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0"+#define STRING_upper0 STR_u STR_p STR_p STR_e STR_r "\0"+#define STRING_alnum0 STR_a STR_l STR_n STR_u STR_m "\0"+#define STRING_ascii0 STR_a STR_s STR_c STR_i STR_i "\0"+#define STRING_blank0 STR_b STR_l STR_a STR_n STR_k "\0"+#define STRING_cntrl0 STR_c STR_n STR_t STR_r STR_l "\0"+#define STRING_digit0 STR_d STR_i STR_g STR_i STR_t "\0"+#define STRING_graph0 STR_g STR_r STR_a STR_p STR_h "\0"+#define STRING_print0 STR_p STR_r STR_i STR_n STR_t "\0"+#define STRING_punct0 STR_p STR_u STR_n STR_c STR_t "\0"+#define STRING_space0 STR_s STR_p STR_a STR_c STR_e "\0"+#define STRING_word0 STR_w STR_o STR_r STR_d "\0"+#define STRING_xdigit STR_x STR_d STR_i STR_g STR_i STR_t++#define STRING_DEFINE STR_D STR_E STR_F STR_I STR_N STR_E+#define STRING_VERSION STR_V STR_E STR_R STR_S STR_I STR_O STR_N+#define STRING_WEIRD_STARTWORD STR_LEFT_SQUARE_BRACKET STR_COLON STR_LESS_THAN_SIGN STR_COLON STR_RIGHT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET+#define STRING_WEIRD_ENDWORD STR_LEFT_SQUARE_BRACKET STR_COLON STR_GREATER_THAN_SIGN STR_COLON STR_RIGHT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET++#define STRING_CR_RIGHTPAR STR_C STR_R STR_RIGHT_PARENTHESIS+#define STRING_LF_RIGHTPAR STR_L STR_F STR_RIGHT_PARENTHESIS+#define STRING_CRLF_RIGHTPAR STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS+#define STRING_ANY_RIGHTPAR STR_A STR_N STR_Y STR_RIGHT_PARENTHESIS+#define STRING_ANYCRLF_RIGHTPAR STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS+#define STRING_NUL_RIGHTPAR STR_N STR_U STR_L STR_RIGHT_PARENTHESIS+#define STRING_BSR_ANYCRLF_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS+#define STRING_BSR_UNICODE_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_U STR_N STR_I STR_C STR_O STR_D STR_E STR_RIGHT_PARENTHESIS+#define STRING_UTF8_RIGHTPAR STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS+#define STRING_UTF16_RIGHTPAR STR_U STR_T STR_F STR_1 STR_6 STR_RIGHT_PARENTHESIS+#define STRING_UTF32_RIGHTPAR STR_U STR_T STR_F STR_3 STR_2 STR_RIGHT_PARENTHESIS+#define STRING_UTF_RIGHTPAR STR_U STR_T STR_F STR_RIGHT_PARENTHESIS+#define STRING_UCP_RIGHTPAR STR_U STR_C STR_P STR_RIGHT_PARENTHESIS+#define STRING_NO_AUTO_POSSESS_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_A STR_U STR_T STR_O STR_UNDERSCORE STR_P STR_O STR_S STR_S STR_E STR_S STR_S STR_RIGHT_PARENTHESIS+#define STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_D STR_O STR_T STR_S STR_T STR_A STR_R STR_UNDERSCORE STR_A STR_N STR_C STR_H STR_O STR_R STR_RIGHT_PARENTHESIS+#define STRING_NO_JIT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_J STR_I STR_T STR_RIGHT_PARENTHESIS+#define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS+#define STRING_NOTEMPTY_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_RIGHT_PARENTHESIS+#define STRING_NOTEMPTY_ATSTART_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_UNDERSCORE STR_A STR_T STR_S STR_T STR_A STR_R STR_T STR_RIGHT_PARENTHESIS+#define STRING_LIMIT_HEAP_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_H STR_E STR_A STR_P STR_EQUALS_SIGN+#define STRING_LIMIT_MATCH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_M STR_A STR_T STR_C STR_H STR_EQUALS_SIGN+#define STRING_LIMIT_DEPTH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_D STR_E STR_P STR_T STR_H STR_EQUALS_SIGN+#define STRING_LIMIT_RECURSION_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_R STR_E STR_C STR_U STR_R STR_S STR_I STR_O STR_N STR_EQUALS_SIGN+#define STRING_MARK STR_M STR_A STR_R STR_K++#endif /* SUPPORT_UNICODE */++/* -------------------- End of character and string names -------------------*/++/* -------------------- Definitions for compiled patterns -------------------*/++/* Codes for different types of Unicode property */++#define PT_ANY 0 /* Any property - matches all chars */+#define PT_LAMP 1 /* L& - the union of Lu, Ll, Lt */+#define PT_GC 2 /* Specified general characteristic (e.g. L) */+#define PT_PC 3 /* Specified particular characteristic (e.g. Lu) */+#define PT_SC 4 /* Script (e.g. Han) */+#define PT_ALNUM 5 /* Alphanumeric - the union of L and N */+#define PT_SPACE 6 /* Perl space - Z plus 9,10,12,13 */+#define PT_PXSPACE 7 /* POSIX space - Z plus 9,10,11,12,13 */+#define PT_WORD 8 /* Word - L plus N plus underscore */+#define PT_CLIST 9 /* Pseudo-property: match character list */+#define PT_UCNC 10 /* Universal Character nameable character */+#define PT_TABSIZE 11 /* Size of square table for autopossessify tests */++/* The following special properties are used only in XCLASS items, when POSIX+classes are specified and PCRE2_UCP is set - in other words, for Unicode+handling of these classes. They are not available via the \p or \P escapes like+those in the above list, and so they do not take part in the autopossessifying+table. */++#define PT_PXGRAPH 11 /* [:graph:] - characters that mark the paper */+#define PT_PXPRINT 12 /* [:print:] - [:graph:] plus non-control spaces */+#define PT_PXPUNCT 13 /* [:punct:] - punctuation characters */++/* Flag bits and data types for the extended class (OP_XCLASS) for classes that+contain characters with values greater than 255. */++#define XCL_NOT 0x01 /* Flag: this is a negative class */+#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */+#define XCL_HASPROP 0x04 /* Flag: property checks are present. */++#define XCL_END 0 /* Marks end of individual items */+#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */+#define XCL_RANGE 2 /* A range (two multibyte chars) follows */+#define XCL_PROP 3 /* Unicode property (2-byte property code follows) */+#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */++/* These are escaped items that aren't just an encoding of a particular data+value such as \n. They must have non-zero values, as check_escape() returns 0+for a data character. In the escapes[] table in pcre2_compile.c their values+are negated in order to distinguish them from data values.++They must appear here in the same order as in the opcode definitions below, up+to ESC_z. There's a dummy for OP_ALLANY because it corresponds to "." in DOTALL+mode rather than an escape sequence. It is also used for [^] in JavaScript+compatibility mode, and for \C in non-utf mode. In non-DOTALL mode, "." behaves+like \N.++Negative numbers are used to encode a backreference (\1, \2, \3, etc.) in+check_escape(). There are tests in the code for an escape greater than ESC_b+and less than ESC_Z to detect the types that may be repeated. These are the+types that consume characters. If any new escapes are put in between that don't+consume a character, that code will have to change. */++enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s,+ ESC_W, ESC_w, ESC_N, ESC_dum, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H,+ ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z,+ ESC_E, ESC_Q, ESC_g, ESC_k };+++/********************** Opcode definitions ******************/++/****** NOTE NOTE NOTE ******++Starting from 1 (i.e. after OP_END), the values up to OP_EOD must correspond in+order to the list of escapes immediately above. Furthermore, values up to+OP_DOLLM must not be changed without adjusting the table called autoposstab in+pcre2_auto_possess.c.++Whenever this list is updated, the two macro definitions that follow must be+updated to match. The possessification table called "opcode_possessify" in+pcre2_compile.c must also be updated, and also the tables called "coptable"+and "poptable" in pcre2_dfa_match.c.++****** NOTE NOTE NOTE ******/+++/* The values between FIRST_AUTOTAB_OP and LAST_AUTOTAB_RIGHT_OP, inclusive,+are used in a table for deciding whether a repeated character type can be+auto-possessified. */++#define FIRST_AUTOTAB_OP OP_NOT_DIGIT+#define LAST_AUTOTAB_LEFT_OP OP_EXTUNI+#define LAST_AUTOTAB_RIGHT_OP OP_DOLLM++enum {+ OP_END, /* 0 End of pattern */++ /* Values corresponding to backslashed metacharacters */++ OP_SOD, /* 1 Start of data: \A */+ OP_SOM, /* 2 Start of match (subject + offset): \G */+ OP_SET_SOM, /* 3 Set start of match (\K) */+ OP_NOT_WORD_BOUNDARY, /* 4 \B */+ OP_WORD_BOUNDARY, /* 5 \b */+ OP_NOT_DIGIT, /* 6 \D */+ OP_DIGIT, /* 7 \d */+ OP_NOT_WHITESPACE, /* 8 \S */+ OP_WHITESPACE, /* 9 \s */+ OP_NOT_WORDCHAR, /* 10 \W */+ OP_WORDCHAR, /* 11 \w */++ OP_ANY, /* 12 Match any character except newline (\N) */+ OP_ALLANY, /* 13 Match any character */+ OP_ANYBYTE, /* 14 Match any byte (\C); different to OP_ANY for UTF-8 */+ OP_NOTPROP, /* 15 \P (not Unicode property) */+ OP_PROP, /* 16 \p (Unicode property) */+ OP_ANYNL, /* 17 \R (any newline sequence) */+ OP_NOT_HSPACE, /* 18 \H (not horizontal whitespace) */+ OP_HSPACE, /* 19 \h (horizontal whitespace) */+ OP_NOT_VSPACE, /* 20 \V (not vertical whitespace) */+ OP_VSPACE, /* 21 \v (vertical whitespace) */+ OP_EXTUNI, /* 22 \X (extended Unicode sequence */+ OP_EODN, /* 23 End of data or \n at end of data (\Z) */+ OP_EOD, /* 24 End of data (\z) */++ /* Line end assertions */++ OP_DOLL, /* 25 End of line - not multiline */+ OP_DOLLM, /* 26 End of line - multiline */+ OP_CIRC, /* 27 Start of line - not multiline */+ OP_CIRCM, /* 28 Start of line - multiline */++ /* Single characters; caseful must precede the caseless ones, and these+ must remain in this order, and adjacent. */++ OP_CHAR, /* 29 Match one character, casefully */+ OP_CHARI, /* 30 Match one character, caselessly */+ OP_NOT, /* 31 Match one character, not the given one, casefully */+ OP_NOTI, /* 32 Match one character, not the given one, caselessly */++ /* The following sets of 13 opcodes must always be kept in step because+ the offset from the first one is used to generate the others. */++ /* Repeated characters; caseful must precede the caseless ones */++ OP_STAR, /* 33 The maximizing and minimizing versions of */+ OP_MINSTAR, /* 34 these six opcodes must come in pairs, with */+ OP_PLUS, /* 35 the minimizing one second. */+ OP_MINPLUS, /* 36 */+ OP_QUERY, /* 37 */+ OP_MINQUERY, /* 38 */++ OP_UPTO, /* 39 From 0 to n matches of one character, caseful*/+ OP_MINUPTO, /* 40 */+ OP_EXACT, /* 41 Exactly n matches */++ OP_POSSTAR, /* 42 Possessified star, caseful */+ OP_POSPLUS, /* 43 Possessified plus, caseful */+ OP_POSQUERY, /* 44 Posesssified query, caseful */+ OP_POSUPTO, /* 45 Possessified upto, caseful */++ /* Repeated characters; caseless must follow the caseful ones */++ OP_STARI, /* 46 */+ OP_MINSTARI, /* 47 */+ OP_PLUSI, /* 48 */+ OP_MINPLUSI, /* 49 */+ OP_QUERYI, /* 50 */+ OP_MINQUERYI, /* 51 */++ OP_UPTOI, /* 52 From 0 to n matches of one character, caseless */+ OP_MINUPTOI, /* 53 */+ OP_EXACTI, /* 54 */++ OP_POSSTARI, /* 55 Possessified star, caseless */+ OP_POSPLUSI, /* 56 Possessified plus, caseless */+ OP_POSQUERYI, /* 57 Posesssified query, caseless */+ OP_POSUPTOI, /* 58 Possessified upto, caseless */++ /* The negated ones must follow the non-negated ones, and match them */+ /* Negated repeated character, caseful; must precede the caseless ones */++ OP_NOTSTAR, /* 59 The maximizing and minimizing versions of */+ OP_NOTMINSTAR, /* 60 these six opcodes must come in pairs, with */+ OP_NOTPLUS, /* 61 the minimizing one second. They must be in */+ OP_NOTMINPLUS, /* 62 exactly the same order as those above. */+ OP_NOTQUERY, /* 63 */+ OP_NOTMINQUERY, /* 64 */++ OP_NOTUPTO, /* 65 From 0 to n matches, caseful */+ OP_NOTMINUPTO, /* 66 */+ OP_NOTEXACT, /* 67 Exactly n matches */++ OP_NOTPOSSTAR, /* 68 Possessified versions, caseful */+ OP_NOTPOSPLUS, /* 69 */+ OP_NOTPOSQUERY, /* 70 */+ OP_NOTPOSUPTO, /* 71 */++ /* Negated repeated character, caseless; must follow the caseful ones */++ OP_NOTSTARI, /* 72 */+ OP_NOTMINSTARI, /* 73 */+ OP_NOTPLUSI, /* 74 */+ OP_NOTMINPLUSI, /* 75 */+ OP_NOTQUERYI, /* 76 */+ OP_NOTMINQUERYI, /* 77 */++ OP_NOTUPTOI, /* 78 From 0 to n matches, caseless */+ OP_NOTMINUPTOI, /* 79 */+ OP_NOTEXACTI, /* 80 Exactly n matches */++ OP_NOTPOSSTARI, /* 81 Possessified versions, caseless */+ OP_NOTPOSPLUSI, /* 82 */+ OP_NOTPOSQUERYI, /* 83 */+ OP_NOTPOSUPTOI, /* 84 */++ /* Character types */++ OP_TYPESTAR, /* 85 The maximizing and minimizing versions of */+ OP_TYPEMINSTAR, /* 86 these six opcodes must come in pairs, with */+ OP_TYPEPLUS, /* 87 the minimizing one second. These codes must */+ OP_TYPEMINPLUS, /* 88 be in exactly the same order as those above. */+ OP_TYPEQUERY, /* 89 */+ OP_TYPEMINQUERY, /* 90 */++ OP_TYPEUPTO, /* 91 From 0 to n matches */+ OP_TYPEMINUPTO, /* 92 */+ OP_TYPEEXACT, /* 93 Exactly n matches */++ OP_TYPEPOSSTAR, /* 94 Possessified versions */+ OP_TYPEPOSPLUS, /* 95 */+ OP_TYPEPOSQUERY, /* 96 */+ OP_TYPEPOSUPTO, /* 97 */++ /* These are used for character classes and back references; only the+ first six are the same as the sets above. */++ OP_CRSTAR, /* 98 The maximizing and minimizing versions of */+ OP_CRMINSTAR, /* 99 all these opcodes must come in pairs, with */+ OP_CRPLUS, /* 100 the minimizing one second. These codes must */+ OP_CRMINPLUS, /* 101 be in exactly the same order as those above. */+ OP_CRQUERY, /* 102 */+ OP_CRMINQUERY, /* 103 */++ OP_CRRANGE, /* 104 These are different to the three sets above. */+ OP_CRMINRANGE, /* 105 */++ OP_CRPOSSTAR, /* 106 Possessified versions */+ OP_CRPOSPLUS, /* 107 */+ OP_CRPOSQUERY, /* 108 */+ OP_CRPOSRANGE, /* 109 */++ /* End of quantifier opcodes */++ OP_CLASS, /* 110 Match a character class, chars < 256 only */+ OP_NCLASS, /* 111 Same, but the bitmap was created from a negative+ class - the difference is relevant only when a+ character > 255 is encountered. */+ OP_XCLASS, /* 112 Extended class for handling > 255 chars within the+ class. This does both positive and negative. */+ OP_REF, /* 113 Match a back reference, casefully */+ OP_REFI, /* 114 Match a back reference, caselessly */+ OP_DNREF, /* 115 Match a duplicate name backref, casefully */+ OP_DNREFI, /* 116 Match a duplicate name backref, caselessly */+ OP_RECURSE, /* 117 Match a numbered subpattern (possibly recursive) */+ OP_CALLOUT, /* 118 Call out to external function if provided */+ OP_CALLOUT_STR, /* 119 Call out with string argument */++ OP_ALT, /* 120 Start of alternation */+ OP_KET, /* 121 End of group that doesn't have an unbounded repeat */+ OP_KETRMAX, /* 122 These two must remain together and in this */+ OP_KETRMIN, /* 123 order. They are for groups the repeat for ever. */+ OP_KETRPOS, /* 124 Possessive unlimited repeat. */++ /* The assertions must come before BRA, CBRA, ONCE, and COND. */++ OP_REVERSE, /* 125 Move pointer back - used in lookbehind assertions */+ OP_ASSERT, /* 126 Positive lookahead */+ OP_ASSERT_NOT, /* 127 Negative lookahead */+ OP_ASSERTBACK, /* 128 Positive lookbehind */+ OP_ASSERTBACK_NOT, /* 129 Negative lookbehind */+ OP_ASSERT_NA, /* 130 Positive non-atomic lookahead */+ OP_ASSERTBACK_NA, /* 131 Positive non-atomic lookbehind */++ /* ONCE, SCRIPT_RUN, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come+ immediately after the assertions, with ONCE first, as there's a test for >=+ ONCE for a subpattern that isn't an assertion. The POS versions must+ immediately follow the non-POS versions in each case. */++ OP_ONCE, /* 132 Atomic group, contains captures */+ OP_SCRIPT_RUN, /* 133 Non-capture, but check characters' scripts */+ OP_BRA, /* 134 Start of non-capturing bracket */+ OP_BRAPOS, /* 135 Ditto, with unlimited, possessive repeat */+ OP_CBRA, /* 136 Start of capturing bracket */+ OP_CBRAPOS, /* 137 Ditto, with unlimited, possessive repeat */+ OP_COND, /* 138 Conditional group */++ /* These five must follow the previous five, in the same order. There's a+ check for >= SBRA to distinguish the two sets. */++ OP_SBRA, /* 139 Start of non-capturing bracket, check empty */+ OP_SBRAPOS, /* 149 Ditto, with unlimited, possessive repeat */+ OP_SCBRA, /* 141 Start of capturing bracket, check empty */+ OP_SCBRAPOS, /* 142 Ditto, with unlimited, possessive repeat */+ OP_SCOND, /* 143 Conditional group, check empty */++ /* The next two pairs must (respectively) be kept together. */++ OP_CREF, /* 144 Used to hold a capture number as condition */+ OP_DNCREF, /* 145 Used to point to duplicate names as a condition */+ OP_RREF, /* 146 Used to hold a recursion number as condition */+ OP_DNRREF, /* 147 Used to point to duplicate names as a condition */+ OP_FALSE, /* 148 Always false (used by DEFINE and VERSION) */+ OP_TRUE, /* 149 Always true (used by VERSION) */++ OP_BRAZERO, /* 150 These two must remain together and in this */+ OP_BRAMINZERO, /* 151 order. */+ OP_BRAPOSZERO, /* 152 */++ /* These are backtracking control verbs */++ OP_MARK, /* 153 always has an argument */+ OP_PRUNE, /* 154 */+ OP_PRUNE_ARG, /* 155 same, but with argument */+ OP_SKIP, /* 156 */+ OP_SKIP_ARG, /* 157 same, but with argument */+ OP_THEN, /* 158 */+ OP_THEN_ARG, /* 159 same, but with argument */+ OP_COMMIT, /* 160 */+ OP_COMMIT_ARG, /* 161 same, but with argument */++ /* These are forced failure and success verbs. FAIL and ACCEPT do accept an+ argument, but these cases can be compiled as, for example, (*MARK:X)(*FAIL)+ without the need for a special opcode. */++ OP_FAIL, /* 162 */+ OP_ACCEPT, /* 163 */+ OP_ASSERT_ACCEPT, /* 164 Used inside assertions */+ OP_CLOSE, /* 165 Used before OP_ACCEPT to close open captures */++ /* This is used to skip a subpattern with a {0} quantifier */++ OP_SKIPZERO, /* 166 */++ /* This is used to identify a DEFINE group during compilation so that it can+ be checked for having only one branch. It is changed to OP_FALSE before+ compilation finishes. */++ OP_DEFINE, /* 167 */++ /* This is not an opcode, but is used to check that tables indexed by opcode+ are the correct length, in order to catch updating errors - there have been+ some in the past. */++ OP_TABLE_LENGTH++};++/* *** NOTE NOTE NOTE *** Whenever the list above is updated, the two macro+definitions that follow must also be updated to match. There are also tables+called "opcode_possessify" in pcre2_compile.c and "coptable" and "poptable" in+pcre2_dfa_match.c that must be updated. */+++/* This macro defines textual names for all the opcodes. These are used only+for debugging, and some of them are only partial names. The macro is referenced+only in pcre2_printint.c, which fills out the full names in many cases (and in+some cases doesn't actually use these names at all). */++#define OP_NAME_LIST \+ "End", "\\A", "\\G", "\\K", "\\B", "\\b", "\\D", "\\d", \+ "\\S", "\\s", "\\W", "\\w", "Any", "AllAny", "Anybyte", \+ "notprop", "prop", "\\R", "\\H", "\\h", "\\V", "\\v", \+ "extuni", "\\Z", "\\z", \+ "$", "$", "^", "^", "char", "chari", "not", "noti", \+ "*", "*?", "+", "+?", "?", "??", \+ "{", "{", "{", \+ "*+","++", "?+", "{", \+ "*", "*?", "+", "+?", "?", "??", \+ "{", "{", "{", \+ "*+","++", "?+", "{", \+ "*", "*?", "+", "+?", "?", "??", \+ "{", "{", "{", \+ "*+","++", "?+", "{", \+ "*", "*?", "+", "+?", "?", "??", \+ "{", "{", "{", \+ "*+","++", "?+", "{", \+ "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \+ "*+","++", "?+", "{", \+ "*", "*?", "+", "+?", "?", "??", "{", "{", \+ "*+","++", "?+", "{", \+ "class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \+ "Recurse", "Callout", "CalloutStr", \+ "Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \+ "Reverse", "Assert", "Assert not", \+ "Assert back", "Assert back not", \+ "Non-atomic assert", "Non-atomic assert back", \+ "Once", \+ "Script run", \+ "Bra", "BraPos", "CBra", "CBraPos", \+ "Cond", \+ "SBra", "SBraPos", "SCBra", "SCBraPos", \+ "SCond", \+ "Cond ref", "Cond dnref", "Cond rec", "Cond dnrec", \+ "Cond false", "Cond true", \+ "Brazero", "Braminzero", "Braposzero", \+ "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \+ "*THEN", "*THEN", "*COMMIT", "*COMMIT", "*FAIL", \+ "*ACCEPT", "*ASSERT_ACCEPT", \+ "Close", "Skip zero", "Define"+++/* This macro defines the length of fixed length operations in the compiled+regex. The lengths are used when searching for specific things, and also in the+debugging printing of a compiled regex. We use a macro so that it can be+defined close to the definitions of the opcodes themselves.++As things have been extended, some of these are no longer fixed lenths, but are+minima instead. For example, the length of a single-character repeat may vary+in UTF-8 mode. The code that uses this table must know about such things. */++#define OP_LENGTHS \+ 1, /* End */ \+ 1, 1, 1, 1, 1, /* \A, \G, \K, \B, \b */ \+ 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */ \+ 1, 1, 1, /* Any, AllAny, Anybyte */ \+ 3, 3, /* \P, \p */ \+ 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */ \+ 1, /* \X */ \+ 1, 1, 1, 1, 1, 1, /* \Z, \z, $, $M ^, ^M */ \+ 2, /* Char - the minimum length */ \+ 2, /* Chari - the minimum length */ \+ 2, /* not */ \+ 2, /* noti */ \+ /* Positive single-char repeats ** These are */ \+ 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** minima in */ \+ 2+IMM2_SIZE, 2+IMM2_SIZE, /* upto, minupto ** mode */ \+ 2+IMM2_SIZE, /* exact */ \+ 2, 2, 2, 2+IMM2_SIZE, /* *+, ++, ?+, upto+ */ \+ 2, 2, 2, 2, 2, 2, /* *I, *?I, +I, +?I, ?I, ??I ** UTF-8 */ \+ 2+IMM2_SIZE, 2+IMM2_SIZE, /* upto I, minupto I */ \+ 2+IMM2_SIZE, /* exact I */ \+ 2, 2, 2, 2+IMM2_SIZE, /* *+I, ++I, ?+I, upto+I */ \+ /* Negative single-char repeats - only for chars < 256 */ \+ 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \+ 2+IMM2_SIZE, 2+IMM2_SIZE, /* NOT upto, minupto */ \+ 2+IMM2_SIZE, /* NOT exact */ \+ 2, 2, 2, 2+IMM2_SIZE, /* Possessive NOT *, +, ?, upto */ \+ 2, 2, 2, 2, 2, 2, /* NOT *I, *?I, +I, +?I, ?I, ??I */ \+ 2+IMM2_SIZE, 2+IMM2_SIZE, /* NOT upto I, minupto I */ \+ 2+IMM2_SIZE, /* NOT exact I */ \+ 2, 2, 2, 2+IMM2_SIZE, /* Possessive NOT *I, +I, ?I, upto I */ \+ /* Positive type repeats */ \+ 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \+ 2+IMM2_SIZE, 2+IMM2_SIZE, /* Type upto, minupto */ \+ 2+IMM2_SIZE, /* Type exact */ \+ 2, 2, 2, 2+IMM2_SIZE, /* Possessive *+, ++, ?+, upto+ */ \+ /* Character class & ref repeats */ \+ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \+ 1+2*IMM2_SIZE, 1+2*IMM2_SIZE, /* CRRANGE, CRMINRANGE */ \+ 1, 1, 1, 1+2*IMM2_SIZE, /* Possessive *+, ++, ?+, CRPOSRANGE */ \+ 1+(32/sizeof(PCRE2_UCHAR)), /* CLASS */ \+ 1+(32/sizeof(PCRE2_UCHAR)), /* NCLASS */ \+ 0, /* XCLASS - variable length */ \+ 1+IMM2_SIZE, /* REF */ \+ 1+IMM2_SIZE, /* REFI */ \+ 1+2*IMM2_SIZE, /* DNREF */ \+ 1+2*IMM2_SIZE, /* DNREFI */ \+ 1+LINK_SIZE, /* RECURSE */ \+ 1+2*LINK_SIZE+1, /* CALLOUT */ \+ 0, /* CALLOUT_STR - variable length */ \+ 1+LINK_SIZE, /* Alt */ \+ 1+LINK_SIZE, /* Ket */ \+ 1+LINK_SIZE, /* KetRmax */ \+ 1+LINK_SIZE, /* KetRmin */ \+ 1+LINK_SIZE, /* KetRpos */ \+ 1+LINK_SIZE, /* Reverse */ \+ 1+LINK_SIZE, /* Assert */ \+ 1+LINK_SIZE, /* Assert not */ \+ 1+LINK_SIZE, /* Assert behind */ \+ 1+LINK_SIZE, /* Assert behind not */ \+ 1+LINK_SIZE, /* NA Assert */ \+ 1+LINK_SIZE, /* NA Assert behind */ \+ 1+LINK_SIZE, /* ONCE */ \+ 1+LINK_SIZE, /* SCRIPT_RUN */ \+ 1+LINK_SIZE, /* BRA */ \+ 1+LINK_SIZE, /* BRAPOS */ \+ 1+LINK_SIZE+IMM2_SIZE, /* CBRA */ \+ 1+LINK_SIZE+IMM2_SIZE, /* CBRAPOS */ \+ 1+LINK_SIZE, /* COND */ \+ 1+LINK_SIZE, /* SBRA */ \+ 1+LINK_SIZE, /* SBRAPOS */ \+ 1+LINK_SIZE+IMM2_SIZE, /* SCBRA */ \+ 1+LINK_SIZE+IMM2_SIZE, /* SCBRAPOS */ \+ 1+LINK_SIZE, /* SCOND */ \+ 1+IMM2_SIZE, 1+2*IMM2_SIZE, /* CREF, DNCREF */ \+ 1+IMM2_SIZE, 1+2*IMM2_SIZE, /* RREF, DNRREF */ \+ 1, 1, /* FALSE, TRUE */ \+ 1, 1, 1, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ \+ 3, 1, 3, /* MARK, PRUNE, PRUNE_ARG */ \+ 1, 3, /* SKIP, SKIP_ARG */ \+ 1, 3, /* THEN, THEN_ARG */ \+ 1, 3, /* COMMIT, COMMIT_ARG */ \+ 1, 1, 1, /* FAIL, ACCEPT, ASSERT_ACCEPT */ \+ 1+IMM2_SIZE, 1, /* CLOSE, SKIPZERO */ \+ 1 /* DEFINE */++/* A magic value for OP_RREF to indicate the "any recursion" condition. */++#define RREF_ANY 0xffff+++/* ---------- Private structures that are mode-independent. ---------- */++/* Structure to hold data for custom memory management. */++typedef struct pcre2_memctl {+ void * (*malloc)(size_t, void *);+ void (*free)(void *, void *);+ void *memory_data;+} pcre2_memctl;++/* Structure for building a chain of open capturing subpatterns during+compiling, so that instructions to close them can be compiled when (*ACCEPT) is+encountered. */++typedef struct open_capitem {+ struct open_capitem *next; /* Chain link */+ uint16_t number; /* Capture number */+ uint16_t assert_depth; /* Assertion depth when opened */+} open_capitem;++/* Layout of the UCP type table that translates property names into types and+codes. Each entry used to point directly to a name, but to reduce the number of+relocations in shared libraries, it now has an offset into a single string+instead. */++typedef struct {+ uint16_t name_offset;+ uint16_t type;+ uint16_t value;+} ucp_type_table;++/* Unicode character database (UCD) record format */++typedef struct {+ uint8_t script; /* ucp_Arabic, etc. */+ uint8_t chartype; /* ucp_Cc, etc. (general categories) */+ uint8_t gbprop; /* ucp_gbControl, etc. (grapheme break property) */+ uint8_t caseset; /* offset to multichar other cases or zero */+ int32_t other_case; /* offset to other case, or zero if none */+ int16_t scriptx; /* script extension value */+ int16_t dummy; /* spare - to round to multiple of 4 bytes */+} ucd_record;++/* UCD access macros */++#define UCD_BLOCK_SIZE 128+#define REAL_GET_UCD(ch) (PRIV(ucd_records) + \+ PRIV(ucd_stage2)[PRIV(ucd_stage1)[(int)(ch) / UCD_BLOCK_SIZE] * \+ UCD_BLOCK_SIZE + (int)(ch) % UCD_BLOCK_SIZE])++#if PCRE2_CODE_UNIT_WIDTH == 32+#define GET_UCD(ch) ((ch > MAX_UTF_CODE_POINT)? \+ PRIV(dummy_ucd_record) : REAL_GET_UCD(ch))+#else+#define GET_UCD(ch) REAL_GET_UCD(ch)+#endif++#define UCD_CHARTYPE(ch) GET_UCD(ch)->chartype+#define UCD_SCRIPT(ch) GET_UCD(ch)->script+#define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)]+#define UCD_GRAPHBREAK(ch) GET_UCD(ch)->gbprop+#define UCD_CASESET(ch) GET_UCD(ch)->caseset+#define UCD_OTHERCASE(ch) ((uint32_t)((int)ch + (int)(GET_UCD(ch)->other_case)))+#define UCD_SCRIPTX(ch) GET_UCD(ch)->scriptx++/* Header for serialized pcre2 codes. */++typedef struct pcre2_serialized_data {+ uint32_t magic;+ uint32_t version;+ uint32_t config;+ int32_t number_of_codes;+} pcre2_serialized_data;++++/* ----------------- Items that need PCRE2_CODE_UNIT_WIDTH ----------------- */++/* When this file is included by pcre2test, PCRE2_CODE_UNIT_WIDTH is defined as+0, so the following items are omitted. */++#if defined PCRE2_CODE_UNIT_WIDTH && PCRE2_CODE_UNIT_WIDTH != 0++/* EBCDIC is supported only for the 8-bit library. */++#if defined EBCDIC && PCRE2_CODE_UNIT_WIDTH != 8+#error EBCDIC is not supported for the 16-bit or 32-bit libraries+#endif++/* This is the largest non-UTF code point. */++#define MAX_NON_UTF_CHAR (0xffffffffU >> (32 - PCRE2_CODE_UNIT_WIDTH))++/* Internal shared data tables and variables. These are used by more than one+of the exported public functions. They have to be "external" in the C sense,+but are not part of the PCRE2 public API. Although the data for some of them is+identical in all libraries, they must have different names so that multiple+libraries can be simultaneously linked to a single application. However, UTF-8+tables are needed only when compiling the 8-bit library. */++#if PCRE2_CODE_UNIT_WIDTH == 8+extern const int PRIV(utf8_table1)[];+extern const int PRIV(utf8_table1_size);+extern const int PRIV(utf8_table2)[];+extern const int PRIV(utf8_table3)[];+extern const uint8_t PRIV(utf8_table4)[];+#endif++#define _pcre2_OP_lengths PCRE2_SUFFIX(_pcre2_OP_lengths_)+#define _pcre2_callout_end_delims PCRE2_SUFFIX(_pcre2_callout_end_delims_)+#define _pcre2_callout_start_delims PCRE2_SUFFIX(_pcre2_callout_start_delims_)+#define _pcre2_default_compile_context PCRE2_SUFFIX(_pcre2_default_compile_context_)+#define _pcre2_default_convert_context PCRE2_SUFFIX(_pcre2_default_convert_context_)+#define _pcre2_default_match_context PCRE2_SUFFIX(_pcre2_default_match_context_)+#define _pcre2_default_tables PCRE2_SUFFIX(_pcre2_default_tables_)+#if PCRE2_CODE_UNIT_WIDTH == 32+#define _pcre2_dummy_ucd_record PCRE2_SUFFIX(_pcre2_dummy_ucd_record_)+#endif+#define _pcre2_hspace_list PCRE2_SUFFIX(_pcre2_hspace_list_)+#define _pcre2_vspace_list PCRE2_SUFFIX(_pcre2_vspace_list_)+#define _pcre2_ucd_caseless_sets PCRE2_SUFFIX(_pcre2_ucd_caseless_sets_)+#define _pcre2_ucd_digit_sets PCRE2_SUFFIX(_pcre2_ucd_digit_sets_)+#define _pcre2_ucd_script_sets PCRE2_SUFFIX(_pcre2_ucd_script_sets_)+#define _pcre2_ucd_records PCRE2_SUFFIX(_pcre2_ucd_records_)+#define _pcre2_ucd_stage1 PCRE2_SUFFIX(_pcre2_ucd_stage1_)+#define _pcre2_ucd_stage2 PCRE2_SUFFIX(_pcre2_ucd_stage2_)+#define _pcre2_ucp_gbtable PCRE2_SUFFIX(_pcre2_ucp_gbtable_)+#define _pcre2_ucp_gentype PCRE2_SUFFIX(_pcre2_ucp_gentype_)+#define _pcre2_ucp_typerange PCRE2_SUFFIX(_pcre2_ucp_typerange_)+#define _pcre2_unicode_version PCRE2_SUFFIX(_pcre2_unicode_version_)+#define _pcre2_utt PCRE2_SUFFIX(_pcre2_utt_)+#define _pcre2_utt_names PCRE2_SUFFIX(_pcre2_utt_names_)+#define _pcre2_utt_size PCRE2_SUFFIX(_pcre2_utt_size_)++extern const uint8_t PRIV(OP_lengths)[];+extern const uint32_t PRIV(callout_end_delims)[];+extern const uint32_t PRIV(callout_start_delims)[];+extern const pcre2_compile_context PRIV(default_compile_context);+extern const pcre2_convert_context PRIV(default_convert_context);+extern const pcre2_match_context PRIV(default_match_context);+extern const uint8_t PRIV(default_tables)[];+extern const uint32_t PRIV(hspace_list)[];+extern const uint32_t PRIV(vspace_list)[];+extern const uint32_t PRIV(ucd_caseless_sets)[];+extern const uint32_t PRIV(ucd_digit_sets)[];+extern const uint8_t PRIV(ucd_script_sets)[];+extern const ucd_record PRIV(ucd_records)[];+#if PCRE2_CODE_UNIT_WIDTH == 32+extern const ucd_record PRIV(dummy_ucd_record)[];+#endif+extern const uint16_t PRIV(ucd_stage1)[];+extern const uint16_t PRIV(ucd_stage2)[];+extern const uint32_t PRIV(ucp_gbtable)[];+extern const uint32_t PRIV(ucp_gentype)[];+#ifdef SUPPORT_JIT+extern const int PRIV(ucp_typerange)[];+#endif+extern const char *PRIV(unicode_version);+extern const ucp_type_table PRIV(utt)[];+extern const char PRIV(utt_names)[];+extern const size_t PRIV(utt_size);++/* Mode-dependent macros and hidden and private structures are defined in a+separate file so that pcre2test can include them at all supported widths. When+compiling the library, PCRE2_CODE_UNIT_WIDTH will be defined, and we can+include them at the appropriate width, after setting up suffix macros for the+private structures. */++#define branch_chain PCRE2_SUFFIX(branch_chain_)+#define compile_block PCRE2_SUFFIX(compile_block_)+#define dfa_match_block PCRE2_SUFFIX(dfa_match_block_)+#define match_block PCRE2_SUFFIX(match_block_)+#define named_group PCRE2_SUFFIX(named_group_)++#include "pcre2_intmodedep.h"++/* Private "external" functions. These are internal functions that are called+from modules other than the one in which they are defined. They have to be+"external" in the C sense, but are not part of the PCRE2 public API. They are+not referenced from pcre2test, and must not be defined when no code unit width+is available. */++#define _pcre2_auto_possessify PCRE2_SUFFIX(_pcre2_auto_possessify_)+#define _pcre2_check_escape PCRE2_SUFFIX(_pcre2_check_escape_)+#define _pcre2_extuni PCRE2_SUFFIX(_pcre2_extuni_)+#define _pcre2_find_bracket PCRE2_SUFFIX(_pcre2_find_bracket_)+#define _pcre2_is_newline PCRE2_SUFFIX(_pcre2_is_newline_)+#define _pcre2_jit_free_rodata PCRE2_SUFFIX(_pcre2_jit_free_rodata_)+#define _pcre2_jit_free PCRE2_SUFFIX(_pcre2_jit_free_)+#define _pcre2_jit_get_size PCRE2_SUFFIX(_pcre2_jit_get_size_)+#define _pcre2_jit_get_target PCRE2_SUFFIX(_pcre2_jit_get_target_)+#define _pcre2_memctl_malloc PCRE2_SUFFIX(_pcre2_memctl_malloc_)+#define _pcre2_ord2utf PCRE2_SUFFIX(_pcre2_ord2utf_)+#define _pcre2_script_run PCRE2_SUFFIX(_pcre2_script_run_)+#define _pcre2_strcmp PCRE2_SUFFIX(_pcre2_strcmp_)+#define _pcre2_strcmp_c8 PCRE2_SUFFIX(_pcre2_strcmp_c8_)+#define _pcre2_strcpy_c8 PCRE2_SUFFIX(_pcre2_strcpy_c8_)+#define _pcre2_strlen PCRE2_SUFFIX(_pcre2_strlen_)+#define _pcre2_strncmp PCRE2_SUFFIX(_pcre2_strncmp_)+#define _pcre2_strncmp_c8 PCRE2_SUFFIX(_pcre2_strncmp_c8_)+#define _pcre2_study PCRE2_SUFFIX(_pcre2_study_)+#define _pcre2_valid_utf PCRE2_SUFFIX(_pcre2_valid_utf_)+#define _pcre2_was_newline PCRE2_SUFFIX(_pcre2_was_newline_)+#define _pcre2_xclass PCRE2_SUFFIX(_pcre2_xclass_)++extern int _pcre2_auto_possessify(PCRE2_UCHAR *,+ const compile_block *);+extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *,+ int *, uint32_t, uint32_t, BOOL, compile_block *);+extern PCRE2_SPTR _pcre2_extuni(uint32_t, PCRE2_SPTR, PCRE2_SPTR, PCRE2_SPTR,+ BOOL, int *);+extern PCRE2_SPTR _pcre2_find_bracket(PCRE2_SPTR, BOOL, int);+extern BOOL _pcre2_is_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR,+ uint32_t *, BOOL);+extern void _pcre2_jit_free_rodata(void *, void *);+extern void _pcre2_jit_free(void *, pcre2_memctl *);+extern size_t _pcre2_jit_get_size(void *);+const char * _pcre2_jit_get_target(void);+extern void * _pcre2_memctl_malloc(size_t, pcre2_memctl *);+extern unsigned int _pcre2_ord2utf(uint32_t, PCRE2_UCHAR *);+extern BOOL _pcre2_script_run(PCRE2_SPTR, PCRE2_SPTR, BOOL);+extern int _pcre2_strcmp(PCRE2_SPTR, PCRE2_SPTR);+extern int _pcre2_strcmp_c8(PCRE2_SPTR, const char *);+extern PCRE2_SIZE _pcre2_strcpy_c8(PCRE2_UCHAR *, const char *);+extern PCRE2_SIZE _pcre2_strlen(PCRE2_SPTR);+extern int _pcre2_strncmp(PCRE2_SPTR, PCRE2_SPTR, size_t);+extern int _pcre2_strncmp_c8(PCRE2_SPTR, const char *, size_t);+extern int _pcre2_study(pcre2_real_code *);+extern int _pcre2_valid_utf(PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE *);+extern BOOL _pcre2_was_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR,+ uint32_t *, BOOL);+extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, BOOL);++/* This function is needed only when memmove() is not available. */++#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)+#define _pcre2_memmove PCRE2_SUFFIX(_pcre2_memmove)+extern void * _pcre2_memmove(void *, const void *, size_t);+#endif++#endif /* PCRE2_CODE_UNIT_WIDTH */+#endif /* PCRE2_INTERNAL_H_IDEMPOTENT_GUARD */++/* End of pcre2_internal.h */
+ src/c/pcre2/src/pcre2_intmodedep.h view
@@ -0,0 +1,923 @@+/*************************************************+* 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) 2016-2018 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.+-----------------------------------------------------------------------------+*/+++/* This module contains mode-dependent macro and structure definitions. The+file is #included by pcre2_internal.h if PCRE2_CODE_UNIT_WIDTH is defined.+These mode-dependent items are kept in a separate file so that they can also be+#included multiple times for different code unit widths by pcre2test in order+to have access to the hidden structures at all supported widths.++Some of the mode-dependent macros are required at different widths for+different parts of the pcre2test code (in particular, the included+pcre_printint.c file). We undefine them here so that they can be re-defined for+multiple inclusions. Not all of these are used in pcre2test, but it's easier+just to undefine them all. */++#undef ACROSSCHAR+#undef BACKCHAR+#undef BYTES2CU+#undef CHMAX_255+#undef CU2BYTES+#undef FORWARDCHAR+#undef FORWARDCHARTEST+#undef GET+#undef GET2+#undef GETCHAR+#undef GETCHARINC+#undef GETCHARINCTEST+#undef GETCHARLEN+#undef GETCHARLENTEST+#undef GETCHARTEST+#undef GET_EXTRALEN+#undef HAS_EXTRALEN+#undef IMM2_SIZE+#undef MAX_255+#undef MAX_MARK+#undef MAX_PATTERN_SIZE+#undef MAX_UTF_SINGLE_CU+#undef NOT_FIRSTCU+#undef PUT+#undef PUT2+#undef PUT2INC+#undef PUTCHAR+#undef PUTINC+#undef TABLE_GET++++/* -------------------------- MACROS ----------------------------- */++/* PCRE keeps offsets in its compiled code as at least 16-bit quantities+(always stored in big-endian order in 8-bit mode) by default. These are used,+for example, to link from the start of a subpattern to its alternatives and its+end. The use of 16 bits per offset limits the size of an 8-bit compiled regex+to around 64K, which is big enough for almost everybody. However, I received a+request for an even bigger limit. For this reason, and also to make the code+easier to maintain, the storing and loading of offsets from the compiled code+unit string is now handled by the macros that are defined here.++The macros are controlled by the value of LINK_SIZE. This defaults to 2, but+values of 3 or 4 are also supported. */++/* ------------------- 8-bit support ------------------ */++#if PCRE2_CODE_UNIT_WIDTH == 8++#if LINK_SIZE == 2+#define PUT(a,n,d) \+ (a[n] = (PCRE2_UCHAR)((d) >> 8)), \+ (a[(n)+1] = (PCRE2_UCHAR)((d) & 255))+#define GET(a,n) \+ (unsigned int)(((a)[n] << 8) | (a)[(n)+1])+#define MAX_PATTERN_SIZE (1 << 16)++#elif LINK_SIZE == 3+#define PUT(a,n,d) \+ (a[n] = (PCRE2_UCHAR)((d) >> 16)), \+ (a[(n)+1] = (PCRE2_UCHAR)((d) >> 8)), \+ (a[(n)+2] = (PCRE2_UCHAR)((d) & 255))+#define GET(a,n) \+ (unsigned int)(((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2])+#define MAX_PATTERN_SIZE (1 << 24)++#elif LINK_SIZE == 4+#define PUT(a,n,d) \+ (a[n] = (PCRE2_UCHAR)((d) >> 24)), \+ (a[(n)+1] = (PCRE2_UCHAR)((d) >> 16)), \+ (a[(n)+2] = (PCRE2_UCHAR)((d) >> 8)), \+ (a[(n)+3] = (PCRE2_UCHAR)((d) & 255))+#define GET(a,n) \+ (unsigned int)(((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3])+#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */++#else+#error LINK_SIZE must be 2, 3, or 4+#endif+++/* ------------------- 16-bit support ------------------ */++#elif PCRE2_CODE_UNIT_WIDTH == 16++#if LINK_SIZE == 2+#undef LINK_SIZE+#define LINK_SIZE 1+#define PUT(a,n,d) \+ (a[n] = (PCRE2_UCHAR)(d))+#define GET(a,n) \+ (a[n])+#define MAX_PATTERN_SIZE (1 << 16)++#elif LINK_SIZE == 3 || LINK_SIZE == 4+#undef LINK_SIZE+#define LINK_SIZE 2+#define PUT(a,n,d) \+ (a[n] = (PCRE2_UCHAR)((d) >> 16)), \+ (a[(n)+1] = (PCRE2_UCHAR)((d) & 65535))+#define GET(a,n) \+ (unsigned int)(((a)[n] << 16) | (a)[(n)+1])+#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */++#else+#error LINK_SIZE must be 2, 3, or 4+#endif+++/* ------------------- 32-bit support ------------------ */++#elif PCRE2_CODE_UNIT_WIDTH == 32+#undef LINK_SIZE+#define LINK_SIZE 1+#define PUT(a,n,d) \+ (a[n] = (d))+#define GET(a,n) \+ (a[n])+#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */++#else+#error Unsupported compiling mode+#endif+++/* --------------- Other mode-specific macros ----------------- */++/* PCRE uses some other (at least) 16-bit quantities that do not change when+the size of offsets changes. There are used for repeat counts and for other+things such as capturing parenthesis numbers in back references.++Define the number of code units required to hold a 16-bit count/offset, and+macros to load and store such a value. For reasons that I do not understand,+the expression in the 8-bit GET2 macro is treated by gcc as a signed+expression, even when a is declared as unsigned. It seems that any kind of+arithmetic results in a signed value. Hence the cast. */++#if PCRE2_CODE_UNIT_WIDTH == 8+#define IMM2_SIZE 2+#define GET2(a,n) (unsigned int)(((a)[n] << 8) | (a)[(n)+1])+#define PUT2(a,n,d) a[n] = (d) >> 8, a[(n)+1] = (d) & 255++#else /* Code units are 16 or 32 bits */+#define IMM2_SIZE 1+#define GET2(a,n) a[n]+#define PUT2(a,n,d) a[n] = d+#endif++/* Other macros that are different for 8-bit mode. The MAX_255 macro checks+whether its argument, which is assumed to be one code unit, is less than 256.+The CHMAX_255 macro does not assume one code unit. The maximum length of a MARK+name must fit in one code unit; currently it is set to 255 or 65535. The+TABLE_GET macro is used to access elements of tables containing exactly 256+items. Its argument is a code unit. When code points can be greater than 255, a+check is needed before accessing these tables. */++#if PCRE2_CODE_UNIT_WIDTH == 8+#define MAX_255(c) TRUE+#define MAX_MARK ((1u << 8) - 1)+#define TABLE_GET(c, table, default) ((table)[c])+#ifdef SUPPORT_UNICODE+#define SUPPORT_WIDE_CHARS+#define CHMAX_255(c) ((c) <= 255u)+#else+#define CHMAX_255(c) TRUE+#endif /* SUPPORT_UNICODE */++#else /* Code units are 16 or 32 bits */+#define CHMAX_255(c) ((c) <= 255u)+#define MAX_255(c) ((c) <= 255u)+#define MAX_MARK ((1u << 16) - 1)+#define SUPPORT_WIDE_CHARS+#define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default))+#endif+++/* ----------------- Character-handling macros ----------------- */++/* There is a proposed future special "UTF-21" mode, in which only the lowest+21 bits of a 32-bit character are interpreted as UTF, with the remaining 11+high-order bits available to the application for other uses. In preparation for+the future implementation of this mode, there are macros that load a data item+and, if in this special mode, mask it to 21 bits. These macros all have names+starting with UCHAR21. In all other modes, including the normal 32-bit+library, the macros all have the same simple definitions. When the new mode is+implemented, it is expected that these definitions will be varied appropriately+using #ifdef when compiling the library that supports the special mode. */++#define UCHAR21(eptr) (*(eptr))+#define UCHAR21TEST(eptr) (*(eptr))+#define UCHAR21INC(eptr) (*(eptr)++)+#define UCHAR21INCTEST(eptr) (*(eptr)++)++/* When UTF encoding is being used, a character is no longer just a single+byte in 8-bit mode or a single short in 16-bit mode. The macros for character+handling generate simple sequences when used in the basic mode, and more+complicated ones for UTF characters. GETCHARLENTEST and other macros are not+used when UTF is not supported. To make sure they can never even appear when+UTF support is omitted, we don't even define them. */++#ifndef SUPPORT_UNICODE++/* #define MAX_UTF_SINGLE_CU */+/* #define HAS_EXTRALEN(c) */+/* #define GET_EXTRALEN(c) */+/* #define NOT_FIRSTCU(c) */+#define GETCHAR(c, eptr) c = *eptr;+#define GETCHARTEST(c, eptr) c = *eptr;+#define GETCHARINC(c, eptr) c = *eptr++;+#define GETCHARINCTEST(c, eptr) c = *eptr++;+#define GETCHARLEN(c, eptr, len) c = *eptr;+#define PUTCHAR(c, p) (*p = c, 1)+/* #define GETCHARLENTEST(c, eptr, len) */+/* #define BACKCHAR(eptr) */+/* #define FORWARDCHAR(eptr) */+/* #define FORWARCCHARTEST(eptr,end) */+/* #define ACROSSCHAR(condition, eptr, action) */++#else /* SUPPORT_UNICODE */++/* ------------------- 8-bit support ------------------ */++#if PCRE2_CODE_UNIT_WIDTH == 8+#define MAYBE_UTF_MULTI /* UTF chars may use multiple code units */++/* The largest UTF code point that can be encoded as a single code unit. */++#define MAX_UTF_SINGLE_CU 127++/* Tests whether the code point needs extra characters to decode. */++#define HAS_EXTRALEN(c) HASUTF8EXTRALEN(c)++/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.+Otherwise it has an undefined behaviour. */++#define GET_EXTRALEN(c) (PRIV(utf8_table4)[(c) & 0x3fu])++/* Returns TRUE, if the given value is not the first code unit of a UTF+sequence. */++#define NOT_FIRSTCU(c) (((c) & 0xc0u) == 0x80u)++/* Get the next UTF-8 character, not advancing the pointer. This is called when+we know we are in UTF-8 mode. */++#define GETCHAR(c, eptr) \+ c = *eptr; \+ if (c >= 0xc0u) GETUTF8(c, eptr);++/* Get the next UTF-8 character, testing for UTF-8 mode, and not advancing the+pointer. */++#define GETCHARTEST(c, eptr) \+ c = *eptr; \+ if (utf && c >= 0xc0u) GETUTF8(c, eptr);++/* Get the next UTF-8 character, advancing the pointer. This is called when we+know we are in UTF-8 mode. */++#define GETCHARINC(c, eptr) \+ c = *eptr++; \+ if (c >= 0xc0u) GETUTF8INC(c, eptr);++/* Get the next character, testing for UTF-8 mode, and advancing the pointer.+This is called when we don't know if we are in UTF-8 mode. */++#define GETCHARINCTEST(c, eptr) \+ c = *eptr++; \+ if (utf && c >= 0xc0u) GETUTF8INC(c, eptr);++/* Get the next UTF-8 character, not advancing the pointer, incrementing length+if there are extra bytes. This is called when we know we are in UTF-8 mode. */++#define GETCHARLEN(c, eptr, len) \+ c = *eptr; \+ if (c >= 0xc0u) GETUTF8LEN(c, eptr, len);++/* Get the next UTF-8 character, testing for UTF-8 mode, not advancing the+pointer, incrementing length if there are extra bytes. This is called when we+do not know if we are in UTF-8 mode. */++#define GETCHARLENTEST(c, eptr, len) \+ c = *eptr; \+ if (utf && c >= 0xc0u) GETUTF8LEN(c, eptr, len);++/* If the pointer is not at the start of a character, move it back until+it is. This is called only in UTF-8 mode - we don't put a test within the macro+because almost all calls are already within a block of UTF-8 only code. */++#define BACKCHAR(eptr) while((*eptr & 0xc0u) == 0x80u) eptr--++/* Same as above, just in the other direction. */+#define FORWARDCHAR(eptr) while((*eptr & 0xc0u) == 0x80u) eptr+++#define FORWARDCHARTEST(eptr,end) while(eptr < end && (*eptr & 0xc0u) == 0x80u) eptr++++/* Same as above, but it allows a fully customizable form. */+#define ACROSSCHAR(condition, eptr, action) \+ while((condition) && ((*eptr) & 0xc0u) == 0x80u) action++/* Deposit a character into memory, returning the number of code units. */++#define PUTCHAR(c, p) ((utf && c > MAX_UTF_SINGLE_CU)? \+ PRIV(ord2utf)(c,p) : (*p = c, 1))+++/* ------------------- 16-bit support ------------------ */++#elif PCRE2_CODE_UNIT_WIDTH == 16+#define MAYBE_UTF_MULTI /* UTF chars may use multiple code units */++/* The largest UTF code point that can be encoded as a single code unit. */++#define MAX_UTF_SINGLE_CU 65535++/* Tests whether the code point needs extra characters to decode. */++#define HAS_EXTRALEN(c) (((c) & 0xfc00u) == 0xd800u)++/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.+Otherwise it has an undefined behaviour. */++#define GET_EXTRALEN(c) 1++/* Returns TRUE, if the given value is not the first code unit of a UTF+sequence. */++#define NOT_FIRSTCU(c) (((c) & 0xfc00u) == 0xdc00u)++/* Base macro to pick up the low surrogate of a UTF-16 character, not+advancing the pointer. */++#define GETUTF16(c, eptr) \+ { c = (((c & 0x3ffu) << 10) | (eptr[1] & 0x3ffu)) + 0x10000u; }++/* Get the next UTF-16 character, not advancing the pointer. This is called when+we know we are in UTF-16 mode. */++#define GETCHAR(c, eptr) \+ c = *eptr; \+ if ((c & 0xfc00u) == 0xd800u) GETUTF16(c, eptr);++/* Get the next UTF-16 character, testing for UTF-16 mode, and not advancing the+pointer. */++#define GETCHARTEST(c, eptr) \+ c = *eptr; \+ if (utf && (c & 0xfc00u) == 0xd800u) GETUTF16(c, eptr);++/* Base macro to pick up the low surrogate of a UTF-16 character, advancing+the pointer. */++#define GETUTF16INC(c, eptr) \+ { c = (((c & 0x3ffu) << 10) | (*eptr++ & 0x3ffu)) + 0x10000u; }++/* Get the next UTF-16 character, advancing the pointer. This is called when we+know we are in UTF-16 mode. */++#define GETCHARINC(c, eptr) \+ c = *eptr++; \+ if ((c & 0xfc00u) == 0xd800u) GETUTF16INC(c, eptr);++/* Get the next character, testing for UTF-16 mode, and advancing the pointer.+This is called when we don't know if we are in UTF-16 mode. */++#define GETCHARINCTEST(c, eptr) \+ c = *eptr++; \+ if (utf && (c & 0xfc00u) == 0xd800u) GETUTF16INC(c, eptr);++/* Base macro to pick up the low surrogate of a UTF-16 character, not+advancing the pointer, incrementing the length. */++#define GETUTF16LEN(c, eptr, len) \+ { c = (((c & 0x3ffu) << 10) | (eptr[1] & 0x3ffu)) + 0x10000u; len++; }++/* Get the next UTF-16 character, not advancing the pointer, incrementing+length if there is a low surrogate. This is called when we know we are in+UTF-16 mode. */++#define GETCHARLEN(c, eptr, len) \+ c = *eptr; \+ if ((c & 0xfc00u) == 0xd800u) GETUTF16LEN(c, eptr, len);++/* Get the next UTF-816character, testing for UTF-16 mode, not advancing the+pointer, incrementing length if there is a low surrogate. This is called when+we do not know if we are in UTF-16 mode. */++#define GETCHARLENTEST(c, eptr, len) \+ c = *eptr; \+ if (utf && (c & 0xfc00u) == 0xd800u) GETUTF16LEN(c, eptr, len);++/* If the pointer is not at the start of a character, move it back until+it is. This is called only in UTF-16 mode - we don't put a test within the+macro because almost all calls are already within a block of UTF-16 only+code. */++#define BACKCHAR(eptr) if ((*eptr & 0xfc00u) == 0xdc00u) eptr--++/* Same as above, just in the other direction. */+#define FORWARDCHAR(eptr) if ((*eptr & 0xfc00u) == 0xdc00u) eptr+++#define FORWARDCHARTEST(eptr,end) if (eptr < end && (*eptr & 0xfc00u) == 0xdc00u) eptr++++/* Same as above, but it allows a fully customizable form. */+#define ACROSSCHAR(condition, eptr, action) \+ if ((condition) && ((*eptr) & 0xfc00u) == 0xdc00u) action++/* Deposit a character into memory, returning the number of code units. */++#define PUTCHAR(c, p) ((utf && c > MAX_UTF_SINGLE_CU)? \+ PRIV(ord2utf)(c,p) : (*p = c, 1))+++/* ------------------- 32-bit support ------------------ */++#else++/* These are trivial for the 32-bit library, since all UTF-32 characters fit+into one PCRE2_UCHAR unit. */++#define MAX_UTF_SINGLE_CU (0x10ffffu)+#define HAS_EXTRALEN(c) (0)+#define GET_EXTRALEN(c) (0)+#define NOT_FIRSTCU(c) (0)++/* Get the next UTF-32 character, not advancing the pointer. This is called when+we know we are in UTF-32 mode. */++#define GETCHAR(c, eptr) \+ c = *(eptr);++/* Get the next UTF-32 character, testing for UTF-32 mode, and not advancing the+pointer. */++#define GETCHARTEST(c, eptr) \+ c = *(eptr);++/* Get the next UTF-32 character, advancing the pointer. This is called when we+know we are in UTF-32 mode. */++#define GETCHARINC(c, eptr) \+ c = *((eptr)++);++/* Get the next character, testing for UTF-32 mode, and advancing the pointer.+This is called when we don't know if we are in UTF-32 mode. */++#define GETCHARINCTEST(c, eptr) \+ c = *((eptr)++);++/* Get the next UTF-32 character, not advancing the pointer, not incrementing+length (since all UTF-32 is of length 1). This is called when we know we are in+UTF-32 mode. */++#define GETCHARLEN(c, eptr, len) \+ GETCHAR(c, eptr)++/* Get the next UTF-32character, testing for UTF-32 mode, not advancing the+pointer, not incrementing the length (since all UTF-32 is of length 1).+This is called when we do not know if we are in UTF-32 mode. */++#define GETCHARLENTEST(c, eptr, len) \+ GETCHARTEST(c, eptr)++/* If the pointer is not at the start of a character, move it back until+it is. This is called only in UTF-32 mode - we don't put a test within the+macro because almost all calls are already within a block of UTF-32 only+code.++These are all no-ops since all UTF-32 characters fit into one pcre_uchar. */++#define BACKCHAR(eptr) do { } while (0)++/* Same as above, just in the other direction. */++#define FORWARDCHAR(eptr) do { } while (0)+#define FORWARDCHARTEST(eptr,end) do { } while (0)++/* Same as above, but it allows a fully customizable form. */++#define ACROSSCHAR(condition, eptr, action) do { } while (0)++/* Deposit a character into memory, returning the number of code units. */++#define PUTCHAR(c, p) (*p = c, 1)++#endif /* UTF-32 character handling */+#endif /* SUPPORT_UNICODE */+++/* Mode-dependent macros that have the same definition in all modes. */++#define CU2BYTES(x) ((x)*((PCRE2_CODE_UNIT_WIDTH/8)))+#define BYTES2CU(x) ((x)/((PCRE2_CODE_UNIT_WIDTH/8)))+#define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE+#define PUT2INC(a,n,d) PUT2(a,n,d), a += IMM2_SIZE+++/* ----------------------- HIDDEN STRUCTURES ----------------------------- */++/* NOTE: All these structures *must* start with a pcre2_memctl structure. The+code that uses them is simpler because it assumes this. */++/* The real general context structure. At present it holds only data for custom+memory control. */++typedef struct pcre2_real_general_context {+ pcre2_memctl memctl;+} pcre2_real_general_context;++/* The real compile context structure */++typedef struct pcre2_real_compile_context {+ pcre2_memctl memctl;+ int (*stack_guard)(uint32_t, void *);+ void *stack_guard_data;+ const uint8_t *tables;+ PCRE2_SIZE max_pattern_length;+ uint16_t bsr_convention;+ uint16_t newline_convention;+ uint32_t parens_nest_limit;+ uint32_t extra_options;+} pcre2_real_compile_context;++/* The real match context structure. */++typedef struct pcre2_real_match_context {+ pcre2_memctl memctl;+#ifdef SUPPORT_JIT+ pcre2_jit_callback jit_callback;+ void *jit_callback_data;+#endif+ int (*callout)(pcre2_callout_block *, void *);+ void *callout_data;+ int (*substitute_callout)(pcre2_substitute_callout_block *, void *);+ void *substitute_callout_data;+ PCRE2_SIZE offset_limit;+ uint32_t heap_limit;+ uint32_t match_limit;+ uint32_t depth_limit;+} pcre2_real_match_context;++/* The real convert context structure. */++typedef struct pcre2_real_convert_context {+ pcre2_memctl memctl;+ uint32_t glob_separator;+ uint32_t glob_escape;+} pcre2_real_convert_context;++/* The real compiled code structure. The type for the blocksize field is+defined specially because it is required in pcre2_serialize_decode() when+copying the size from possibly unaligned memory into a variable of the same+type. Use a macro rather than a typedef to avoid compiler warnings when this+file is included multiple times by pcre2test. LOOKBEHIND_MAX specifies the+largest lookbehind that is supported. (OP_REVERSE in a pattern has a 16-bit+argument in 8-bit and 16-bit modes, so we need no more than a 16-bit field+here.) */++#undef CODE_BLOCKSIZE_TYPE+#define CODE_BLOCKSIZE_TYPE size_t++#undef LOOKBEHIND_MAX+#define LOOKBEHIND_MAX UINT16_MAX++typedef struct pcre2_real_code {+ pcre2_memctl memctl; /* Memory control fields */+ const uint8_t *tables; /* The character tables */+ void *executable_jit; /* Pointer to JIT code */+ uint8_t start_bitmap[32]; /* Bitmap for starting code unit < 256 */+ CODE_BLOCKSIZE_TYPE blocksize; /* Total (bytes) that was malloc-ed */+ uint32_t magic_number; /* Paranoid and endianness check */+ uint32_t compile_options; /* Options passed to pcre2_compile() */+ uint32_t overall_options; /* Options after processing the pattern */+ uint32_t extra_options; /* Taken from compile_context */+ uint32_t flags; /* Various state flags */+ uint32_t limit_heap; /* Limit set in the pattern */+ uint32_t limit_match; /* Limit set in the pattern */+ uint32_t limit_depth; /* Limit set in the pattern */+ uint32_t first_codeunit; /* Starting code unit */+ uint32_t last_codeunit; /* This codeunit must be seen */+ uint16_t bsr_convention; /* What \R matches */+ uint16_t newline_convention; /* What is a newline? */+ uint16_t max_lookbehind; /* Longest lookbehind (characters) */+ uint16_t minlength; /* Minimum length of match */+ uint16_t top_bracket; /* Highest numbered group */+ uint16_t top_backref; /* Highest numbered back reference */+ uint16_t name_entry_size; /* Size (code units) of table entries */+ uint16_t name_count; /* Number of name entries in the table */+} pcre2_real_code;++/* The real match data structure. Define ovector as large as it can ever+actually be so that array bound checkers don't grumble. Memory for this+structure is obtained by calling pcre2_match_data_create(), which sets the size+as the offset of ovector plus a pair of elements for each capturable string, so+the size varies from call to call. As the maximum number of capturing+subpatterns is 65535 we must allow for 65536 strings to include the overall+match. (See also the heapframe structure below.) */++typedef struct pcre2_real_match_data {+ pcre2_memctl memctl;+ const pcre2_real_code *code; /* The pattern used for the match */+ PCRE2_SPTR subject; /* The subject that was matched */+ PCRE2_SPTR mark; /* Pointer to last mark */+ PCRE2_SIZE leftchar; /* Offset to leftmost code unit */+ PCRE2_SIZE rightchar; /* Offset to rightmost code unit */+ PCRE2_SIZE startchar; /* Offset to starting code unit */+ uint8_t matchedby; /* Type of match (normal, JIT, DFA) */+ uint8_t flags; /* Various flags */+ uint16_t oveccount; /* Number of pairs */+ int rc; /* The return code from the match */+ PCRE2_SIZE ovector[131072]; /* Must be last in the structure */+} pcre2_real_match_data;+++/* ----------------------- PRIVATE STRUCTURES ----------------------------- */++/* These structures are not needed for pcre2test. */++#ifndef PCRE2_PCRE2TEST++/* Structures for checking for mutual recursion when scanning compiled or+parsed code. */++typedef struct recurse_check {+ struct recurse_check *prev;+ PCRE2_SPTR group;+} recurse_check;++typedef struct parsed_recurse_check {+ struct parsed_recurse_check *prev;+ uint32_t *groupptr;+} parsed_recurse_check;++/* Structure for building a cache when filling in recursion offsets. */++typedef struct recurse_cache {+ PCRE2_SPTR group;+ int groupnumber;+} recurse_cache;++/* Structure for maintaining a chain of pointers to the currently incomplete+branches, for testing for left recursion while compiling. */++typedef struct branch_chain {+ struct branch_chain *outer;+ PCRE2_UCHAR *current_branch;+} branch_chain;++/* Structure for building a list of named groups during the first pass of+compiling. */++typedef struct named_group {+ PCRE2_SPTR name; /* Points to the name in the pattern */+ uint32_t number; /* Group number */+ uint16_t length; /* Length of the name */+ uint16_t isdup; /* TRUE if a duplicate */+} named_group;++/* Structure for passing "static" information around between the functions+doing the compiling, so that they are thread-safe. */++typedef struct compile_block {+ pcre2_real_compile_context *cx; /* Points to the compile context */+ const uint8_t *lcc; /* Points to lower casing table */+ const uint8_t *fcc; /* Points to case-flipping table */+ const uint8_t *cbits; /* Points to character type table */+ const uint8_t *ctypes; /* Points to table of type maps */+ PCRE2_SPTR start_workspace; /* The start of working space */+ PCRE2_SPTR start_code; /* The start of the compiled code */+ PCRE2_SPTR start_pattern; /* The start of the pattern */+ PCRE2_SPTR end_pattern; /* The end of the pattern */+ PCRE2_UCHAR *name_table; /* The name/number table */+ PCRE2_SIZE workspace_size; /* Size of workspace */+ PCRE2_SIZE small_ref_offset[10]; /* Offsets for \1 to \9 */+ PCRE2_SIZE erroroffset; /* Offset of error in pattern */+ uint16_t names_found; /* Number of entries so far */+ uint16_t name_entry_size; /* Size of each entry */+ uint16_t parens_depth; /* Depth of nested parentheses */+ uint16_t assert_depth; /* Depth of nested assertions */+ open_capitem *open_caps; /* Chain of open capture items */+ named_group *named_groups; /* Points to vector in pre-compile */+ uint32_t named_group_list_size; /* Number of entries in the list */+ uint32_t external_options; /* External (initial) options */+ uint32_t external_flags; /* External flag bits to be set */+ uint32_t bracount; /* Count of capturing parentheses */+ uint32_t lastcapture; /* Last capture encountered */+ uint32_t *parsed_pattern; /* Parsed pattern buffer */+ uint32_t *parsed_pattern_end; /* Parsed pattern should not get here */+ uint32_t *groupinfo; /* Group info vector */+ uint32_t top_backref; /* Maximum back reference */+ uint32_t backref_map; /* Bitmap of low back refs */+ uint32_t nltype; /* Newline type */+ uint32_t nllen; /* Newline string length */+ uint32_t class_range_start; /* Overall class range start */+ uint32_t class_range_end; /* Overall class range end */+ PCRE2_UCHAR nl[4]; /* Newline string when fixed length */+ int max_lookbehind; /* Maximum lookbehind (characters) */+ int req_varyopt; /* "After variable item" flag for reqbyte */+ BOOL had_accept; /* (*ACCEPT) encountered */+ BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */+ BOOL had_recurse; /* Had a recursion or subroutine call */+ BOOL dupnames; /* Duplicate names exist */+} compile_block;++/* Structure for keeping the properties of the in-memory stack used+by the JIT matcher. */++typedef struct pcre2_real_jit_stack {+ pcre2_memctl memctl;+ void* stack;+} pcre2_real_jit_stack;++/* Structure for items in a linked list that represents an explicit recursive+call within the pattern when running pcre_dfa_match(). */++typedef struct dfa_recursion_info {+ struct dfa_recursion_info *prevrec;+ PCRE2_SPTR subject_position;+ uint32_t group_num;+} dfa_recursion_info;++/* Structure for "stack" frames that are used for remembering backtracking+positions during matching. As these are used in a vector, with the ovector item+being extended, the size of the structure must be a multiple of PCRE2_SIZE. The+only way to check this at compile time is to force an error by generating an+array with a negative size. By putting this in a typedef (which is never used),+we don't generate any code when all is well. */++typedef struct heapframe {++ /* The first set of fields are variables that have to be preserved over calls+ to RRMATCH(), but which do not need to be copied to new frames. */++ PCRE2_SPTR ecode; /* The current position in the pattern */+ PCRE2_SPTR temp_sptr[2]; /* Used for short-term PCRE_SPTR values */+ PCRE2_SIZE length; /* Used for character, string, or code lengths */+ PCRE2_SIZE back_frame; /* Amount to subtract on RRETURN */+ PCRE2_SIZE temp_size; /* Used for short-term PCRE2_SIZE values */+ uint32_t rdepth; /* "Recursion" depth */+ uint32_t group_frame_type; /* Type information for group frames */+ uint32_t temp_32[4]; /* Used for short-term 32-bit or BOOL values */+ uint8_t return_id; /* Where to go on in internal "return" */+ uint8_t op; /* Processing opcode */++ /* At this point, the structure is 16-bit aligned. On most architectures+ the alignment requirement for a pointer will ensure that the eptr field below+ is 32-bit or 64-bit aligned. However, on m68k it is fine to have a pointer+ that is 16-bit aligned. We must therefore ensure that what comes between here+ and eptr is an odd multiple of 16 bits so as to get back into 32-bit+ alignment. This happens naturally when PCRE2_UCHAR is 8 bits wide, but needs+ fudges in the other cases. In the 32-bit case the padding comes first so that+ the occu field itself is 32-bit aligned. Without the padding, this structure+ is no longer a multiple of PCRE2_SIZE on m68k, and the check below fails. */++#if PCRE2_CODE_UNIT_WIDTH == 8+ PCRE2_UCHAR occu[6]; /* Used for other case code units */+#elif PCRE2_CODE_UNIT_WIDTH == 16+ PCRE2_UCHAR occu[2]; /* Used for other case code units */+ uint8_t unused[2]; /* Ensure 32-bit alignment (see above) */+#else+ uint8_t unused[2]; /* Ensure 32-bit alignment (see above) */+ PCRE2_UCHAR occu[1]; /* Used for other case code units */+#endif++ /* The rest have to be copied from the previous frame whenever a new frame+ becomes current. The final field is specified as a large vector so that+ runtime array bound checks don't catch references to it. However, for any+ specific call to pcre2_match() the memory allocated for each frame structure+ allows for exactly the right size ovector for the number of capturing+ parentheses. (See also the comment for pcre2_real_match_data above.) */++ PCRE2_SPTR eptr; /* MUST BE FIRST */+ PCRE2_SPTR start_match; /* Can be adjusted by \K */+ PCRE2_SPTR mark; /* Most recent mark on the success path */+ uint32_t current_recurse; /* Current (deepest) recursion number */+ uint32_t capture_last; /* Most recent capture */+ PCRE2_SIZE last_group_offset; /* Saved offset to most recent group frame */+ PCRE2_SIZE offset_top; /* Offset after highest capture */+ PCRE2_SIZE ovector[131072]; /* Must be last in the structure */+} heapframe;++/* This typedef is a check that the size of the heapframe structure is a+multiple of PCRE2_SIZE. See various comments above. */++typedef char check_heapframe_size[+ ((sizeof(heapframe) % sizeof(PCRE2_SIZE)) == 0)? (+1):(-1)];++/* Structure for passing "static" information around between the functions+doing traditional NFA matching (pcre2_match() and friends). */++typedef struct match_block {+ pcre2_memctl memctl; /* For general use */+ PCRE2_SIZE frame_vector_size; /* Size of a backtracking frame */+ heapframe *match_frames; /* Points to vector of frames */+ heapframe *match_frames_top; /* Points after the end of the vector */+ heapframe *stack_frames; /* The original vector on the stack */+ PCRE2_SIZE heap_limit; /* As it says */+ uint32_t match_limit; /* As it says */+ uint32_t match_limit_depth; /* As it says */+ uint32_t match_call_count; /* Number of times a new frame is created */+ BOOL hitend; /* Hit the end of the subject at some point */+ BOOL hasthen; /* Pattern contains (*THEN) */+ BOOL allowemptypartial; /* Allow empty hard partial */+ const uint8_t *lcc; /* Points to lower casing table */+ const uint8_t *fcc; /* Points to case-flipping table */+ const uint8_t *ctypes; /* Points to table of type maps */+ PCRE2_SIZE start_offset; /* The start offset value */+ PCRE2_SIZE end_offset_top; /* Highwater mark at end of match */+ uint16_t partial; /* PARTIAL options */+ uint16_t bsr_convention; /* \R interpretation */+ uint16_t name_count; /* Number of names in name table */+ uint16_t name_entry_size; /* Size of entry in names table */+ PCRE2_SPTR name_table; /* Table of group names */+ PCRE2_SPTR start_code; /* For use when recursing */+ PCRE2_SPTR start_subject; /* Start of the subject string */+ PCRE2_SPTR check_subject; /* Where UTF-checked from */+ PCRE2_SPTR end_subject; /* End of the subject string */+ PCRE2_SPTR end_match_ptr; /* Subject position at end match */+ PCRE2_SPTR start_used_ptr; /* Earliest consulted character */+ PCRE2_SPTR last_used_ptr; /* Latest consulted character */+ PCRE2_SPTR mark; /* Mark pointer to pass back on success */+ PCRE2_SPTR nomatch_mark; /* Mark pointer to pass back on failure */+ PCRE2_SPTR verb_ecode_ptr; /* For passing back info */+ PCRE2_SPTR verb_skip_ptr; /* For passing back a (*SKIP) name */+ uint32_t verb_current_recurse; /* Current recurse when (*VERB) happens */+ uint32_t moptions; /* Match options */+ uint32_t poptions; /* Pattern options */+ uint32_t skip_arg_count; /* For counting SKIP_ARGs */+ uint32_t ignore_skip_arg; /* For re-run when SKIP arg name not found */+ uint32_t nltype; /* Newline type */+ uint32_t nllen; /* Newline string length */+ PCRE2_UCHAR nl[4]; /* Newline string when fixed */+ pcre2_callout_block *cb; /* Points to a callout block */+ void *callout_data; /* To pass back to callouts */+ int (*callout)(pcre2_callout_block *,void *); /* Callout function or NULL */+} match_block;++/* A similar structure is used for the same purpose by the DFA matching+functions. */++typedef struct dfa_match_block {+ pcre2_memctl memctl; /* For general use */+ PCRE2_SPTR start_code; /* Start of the compiled pattern */+ PCRE2_SPTR start_subject ; /* Start of the subject string */+ PCRE2_SPTR end_subject; /* End of subject string */+ PCRE2_SPTR start_used_ptr; /* Earliest consulted character */+ PCRE2_SPTR last_used_ptr; /* Latest consulted character */+ const uint8_t *tables; /* Character tables */+ PCRE2_SIZE start_offset; /* The start offset value */+ PCRE2_SIZE heap_limit; /* As it says */+ PCRE2_SIZE heap_used; /* As it says */+ uint32_t match_limit; /* As it says */+ uint32_t match_limit_depth; /* As it says */+ uint32_t match_call_count; /* Number of calls of internal function */+ uint32_t moptions; /* Match options */+ uint32_t poptions; /* Pattern options */+ uint32_t nltype; /* Newline type */+ uint32_t nllen; /* Newline string length */+ BOOL allowemptypartial; /* Allow empty hard partial */+ PCRE2_UCHAR nl[4]; /* Newline string when fixed */+ uint16_t bsr_convention; /* \R interpretation */+ pcre2_callout_block *cb; /* Points to a callout block */+ void *callout_data; /* To pass back to callouts */+ int (*callout)(pcre2_callout_block *,void *); /* Callout function or NULL */+ dfa_recursion_info *recursive; /* Linked list of recursion data */+} dfa_match_block;++#endif /* PCRE2_PCRE2TEST */++/* End of pcre2_intmodedep.h */
+ src/c/pcre2/src/pcre2_jit_compile.c view
@@ -0,0 +1,14252 @@+/*************************************************+* 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+ This module by Zoltan Herczeg+ Original API code Copyright (c) 1997-2012 University of Cambridge+ New API code Copyright (c) 2016-2019 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++#include "pcre2_internal.h"++#ifdef SUPPORT_JIT++/* All-in-one: Since we use the JIT compiler only from here,+we just include it. This way we don't need to touch the build+system files. */++#define SLJIT_CONFIG_AUTO 1+#define SLJIT_CONFIG_STATIC 1+#define SLJIT_VERBOSE 0++#ifdef PCRE2_DEBUG+#define SLJIT_DEBUG 1+#else+#define SLJIT_DEBUG 0+#endif++#define SLJIT_MALLOC(size, allocator_data) pcre2_jit_malloc(size, allocator_data)+#define SLJIT_FREE(ptr, allocator_data) pcre2_jit_free(ptr, allocator_data)++static void * pcre2_jit_malloc(size_t size, void *allocator_data)+{+pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);+return allocator->malloc(size, allocator->memory_data);+}++static void pcre2_jit_free(void *ptr, void *allocator_data)+{+pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);+allocator->free(ptr, allocator->memory_data);+}++#include "sljit/sljitLir.c"++#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED+#error Unsupported architecture+#endif++/* Defines for debugging purposes. */++/* 1 - Use unoptimized capturing brackets.+ 2 - Enable capture_last_ptr (includes option 1). */+/* #define DEBUG_FORCE_UNOPTIMIZED_CBRAS 2 */++/* 1 - Always have a control head. */+/* #define DEBUG_FORCE_CONTROL_HEAD 1 */++/* Allocate memory for the regex stack on the real machine stack.+Fast, but limited size. */+#define MACHINE_STACK_SIZE 32768++/* Growth rate for stack allocated by the OS. Should be the multiply+of page size. */+#define STACK_GROWTH_RATE 8192++/* Enable to check that the allocation could destroy temporaries. */+#if defined SLJIT_DEBUG && SLJIT_DEBUG+#define DESTROY_REGISTERS 1+#endif++/*+Short summary about the backtracking mechanism empolyed by the jit code generator:++The code generator follows the recursive nature of the PERL compatible regular+expressions. The basic blocks of regular expressions are condition checkers+whose execute different commands depending on the result of the condition check.+The relationship between the operators can be horizontal (concatenation) and+vertical (sub-expression) (See struct backtrack_common for more details).++ 'ab' - 'a' and 'b' regexps are concatenated+ 'a+' - 'a' is the sub-expression of the '+' operator++The condition checkers are boolean (true/false) checkers. Machine code is generated+for the checker itself and for the actions depending on the result of the checker.+The 'true' case is called as the matching path (expected path), and the other is called as+the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken+branches on the matching path.++ Greedy star operator (*) :+ Matching path: match happens.+ Backtrack path: match failed.+ Non-greedy star operator (*?) :+ Matching path: no need to perform a match.+ Backtrack path: match is required.++The following example shows how the code generated for a capturing bracket+with two alternatives. Let A, B, C, D are arbirary regular expressions, and+we have the following regular expression:++ A(B|C)D++The generated code will be the following:++ A matching path+ '(' matching path (pushing arguments to the stack)+ B matching path+ ')' matching path (pushing arguments to the stack)+ D matching path+ return with successful match++ D backtrack path+ ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")+ B backtrack path+ C expected path+ jump to D matching path+ C backtrack path+ A backtrack path++ Notice, that the order of backtrack code paths are the opposite of the fast+ code paths. In this way the topmost value on the stack is always belong+ to the current backtrack code path. The backtrack path must check+ whether there is a next alternative. If so, it needs to jump back to+ the matching path eventually. Otherwise it needs to clear out its own stack+ frame and continue the execution on the backtrack code paths.+*/++/*+Saved stack frames:++Atomic blocks and asserts require reloading the values of private data+when the backtrack mechanism performed. Because of OP_RECURSE, the data+are not necessarly known in compile time, thus we need a dynamic restore+mechanism.++The stack frames are stored in a chain list, and have the following format:+([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]++Thus we can restore the private data to a particular point in the stack.+*/++typedef struct jit_arguments {+ /* Pointers first. */+ struct sljit_stack *stack;+ PCRE2_SPTR str;+ PCRE2_SPTR begin;+ PCRE2_SPTR end;+ pcre2_match_data *match_data;+ PCRE2_SPTR startchar_ptr;+ PCRE2_UCHAR *mark_ptr;+ int (*callout)(pcre2_callout_block *, void *);+ void *callout_data;+ /* Everything else after. */+ sljit_uw offset_limit;+ sljit_u32 limit_match;+ sljit_u32 oveccount;+ sljit_u32 options;+} jit_arguments;++#define JIT_NUMBER_OF_COMPILE_MODES 3++typedef struct executable_functions {+ void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES];+ void *read_only_data_heads[JIT_NUMBER_OF_COMPILE_MODES];+ sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];+ sljit_u32 top_bracket;+ sljit_u32 limit_match;+} executable_functions;++typedef struct jump_list {+ struct sljit_jump *jump;+ struct jump_list *next;+} jump_list;++typedef struct stub_list {+ struct sljit_jump *start;+ struct sljit_label *quit;+ struct stub_list *next;+} stub_list;++enum frame_types {+ no_frame = -1,+ no_stack = -2+};++enum control_types {+ type_mark = 0,+ type_then_trap = 1+};++enum early_fail_types {+ type_skip = 0,+ type_fail = 1,+ type_fail_range = 2+};++typedef int (SLJIT_FUNC *jit_function)(jit_arguments *args);++/* The following structure is the key data type for the recursive+code generator. It is allocated by compile_matchingpath, and contains+the arguments for compile_backtrackingpath. Must be the first member+of its descendants. */+typedef struct backtrack_common {+ /* Concatenation stack. */+ struct backtrack_common *prev;+ jump_list *nextbacktracks;+ /* Internal stack (for component operators). */+ struct backtrack_common *top;+ jump_list *topbacktracks;+ /* Opcode pointer. */+ PCRE2_SPTR cc;+} backtrack_common;++typedef struct assert_backtrack {+ backtrack_common common;+ jump_list *condfailed;+ /* Less than 0 if a frame is not needed. */+ int framesize;+ /* Points to our private memory word on the stack. */+ int private_data_ptr;+ /* For iterators. */+ struct sljit_label *matchingpath;+} assert_backtrack;++typedef struct bracket_backtrack {+ backtrack_common common;+ /* Where to coninue if an alternative is successfully matched. */+ struct sljit_label *alternative_matchingpath;+ /* For rmin and rmax iterators. */+ struct sljit_label *recursive_matchingpath;+ /* For greedy ? operator. */+ struct sljit_label *zero_matchingpath;+ /* Contains the branches of a failed condition. */+ union {+ /* Both for OP_COND, OP_SCOND. */+ jump_list *condfailed;+ assert_backtrack *assert;+ /* For OP_ONCE. Less than 0 if not needed. */+ int framesize;+ /* For brackets with >3 alternatives. */+ struct sljit_put_label *matching_put_label;+ } u;+ /* Points to our private memory word on the stack. */+ int private_data_ptr;+} bracket_backtrack;++typedef struct bracketpos_backtrack {+ backtrack_common common;+ /* Points to our private memory word on the stack. */+ int private_data_ptr;+ /* Reverting stack is needed. */+ int framesize;+ /* Allocated stack size. */+ int stacksize;+} bracketpos_backtrack;++typedef struct braminzero_backtrack {+ backtrack_common common;+ struct sljit_label *matchingpath;+} braminzero_backtrack;++typedef struct char_iterator_backtrack {+ backtrack_common common;+ /* Next iteration. */+ struct sljit_label *matchingpath;+ union {+ jump_list *backtracks;+ struct {+ unsigned int othercasebit;+ PCRE2_UCHAR chr;+ BOOL enabled;+ } charpos;+ } u;+} char_iterator_backtrack;++typedef struct ref_iterator_backtrack {+ backtrack_common common;+ /* Next iteration. */+ struct sljit_label *matchingpath;+} ref_iterator_backtrack;++typedef struct recurse_entry {+ struct recurse_entry *next;+ /* Contains the function entry label. */+ struct sljit_label *entry_label;+ /* Contains the function entry label. */+ struct sljit_label *backtrack_label;+ /* Collects the entry calls until the function is not created. */+ jump_list *entry_calls;+ /* Collects the backtrack calls until the function is not created. */+ jump_list *backtrack_calls;+ /* Points to the starting opcode. */+ sljit_sw start;+} recurse_entry;++typedef struct recurse_backtrack {+ backtrack_common common;+ /* Return to the matching path. */+ struct sljit_label *matchingpath;+ /* Recursive pattern. */+ recurse_entry *entry;+ /* Pattern is inlined. */+ BOOL inlined_pattern;+} recurse_backtrack;++#define OP_THEN_TRAP OP_TABLE_LENGTH++typedef struct then_trap_backtrack {+ backtrack_common common;+ /* If then_trap is not NULL, this structure contains the real+ then_trap for the backtracking path. */+ struct then_trap_backtrack *then_trap;+ /* Points to the starting opcode. */+ sljit_sw start;+ /* Exit point for the then opcodes of this alternative. */+ jump_list *quit;+ /* Frame size of the current alternative. */+ int framesize;+} then_trap_backtrack;++#define MAX_N_CHARS 12+#define MAX_DIFF_CHARS 5++typedef struct fast_forward_char_data {+ /* Number of characters in the chars array, 255 for any character. */+ sljit_u8 count;+ /* Number of last UTF-8 characters in the chars array. */+ sljit_u8 last_count;+ /* Available characters in the current position. */+ PCRE2_UCHAR chars[MAX_DIFF_CHARS];+} fast_forward_char_data;++#define MAX_CLASS_RANGE_SIZE 4+#define MAX_CLASS_CHARS_SIZE 3++typedef struct compiler_common {+ /* The sljit ceneric compiler. */+ struct sljit_compiler *compiler;+ /* Compiled regular expression. */+ pcre2_real_code *re;+ /* First byte code. */+ PCRE2_SPTR start;+ /* Maps private data offset to each opcode. */+ sljit_s32 *private_data_ptrs;+ /* Chain list of read-only data ptrs. */+ void *read_only_data_head;+ /* Tells whether the capturing bracket is optimized. */+ sljit_u8 *optimized_cbracket;+ /* Tells whether the starting offset is a target of then. */+ sljit_u8 *then_offsets;+ /* Current position where a THEN must jump. */+ then_trap_backtrack *then_trap;+ /* Starting offset of private data for capturing brackets. */+ sljit_s32 cbra_ptr;+ /* Output vector starting point. Must be divisible by 2. */+ sljit_s32 ovector_start;+ /* Points to the starting character of the current match. */+ sljit_s32 start_ptr;+ /* Last known position of the requested byte. */+ sljit_s32 req_char_ptr;+ /* Head of the last recursion. */+ sljit_s32 recursive_head_ptr;+ /* First inspected character for partial matching.+ (Needed for avoiding zero length partial matches.) */+ sljit_s32 start_used_ptr;+ /* Starting pointer for partial soft matches. */+ sljit_s32 hit_start;+ /* Pointer of the match end position. */+ sljit_s32 match_end_ptr;+ /* Points to the marked string. */+ sljit_s32 mark_ptr;+ /* Recursive control verb management chain. */+ sljit_s32 control_head_ptr;+ /* Points to the last matched capture block index. */+ sljit_s32 capture_last_ptr;+ /* Fast forward skipping byte code pointer. */+ PCRE2_SPTR fast_forward_bc_ptr;+ /* Locals used by fast fail optimization. */+ sljit_s32 early_fail_start_ptr;+ sljit_s32 early_fail_end_ptr;++ /* Flipped and lower case tables. */+ const sljit_u8 *fcc;+ sljit_sw lcc;+ /* Mode can be PCRE2_JIT_COMPLETE and others. */+ int mode;+ /* TRUE, when empty match is accepted for partial matching. */+ BOOL allow_empty_partial;+ /* TRUE, when minlength is greater than 0. */+ BOOL might_be_empty;+ /* \K is found in the pattern. */+ BOOL has_set_som;+ /* (*SKIP:arg) is found in the pattern. */+ BOOL has_skip_arg;+ /* (*THEN) is found in the pattern. */+ BOOL has_then;+ /* (*SKIP) or (*SKIP:arg) is found in lookbehind assertion. */+ BOOL has_skip_in_assert_back;+ /* Quit is redirected by recurse, negative assertion, or positive assertion in conditional block. */+ BOOL local_quit_available;+ /* Currently in a positive assertion. */+ BOOL in_positive_assertion;+ /* Newline control. */+ int nltype;+ sljit_u32 nlmax;+ sljit_u32 nlmin;+ int newline;+ int bsr_nltype;+ sljit_u32 bsr_nlmax;+ sljit_u32 bsr_nlmin;+ /* Dollar endonly. */+ int endonly;+ /* Tables. */+ sljit_sw ctypes;+ /* Named capturing brackets. */+ PCRE2_SPTR name_table;+ sljit_sw name_count;+ sljit_sw name_entry_size;++ /* Labels and jump lists. */+ struct sljit_label *partialmatchlabel;+ struct sljit_label *quit_label;+ struct sljit_label *abort_label;+ struct sljit_label *accept_label;+ struct sljit_label *ff_newline_shortcut;+ stub_list *stubs;+ recurse_entry *entries;+ recurse_entry *currententry;+ jump_list *partialmatch;+ jump_list *quit;+ jump_list *positive_assertion_quit;+ jump_list *abort;+ jump_list *failed_match;+ jump_list *accept;+ jump_list *calllimit;+ jump_list *stackalloc;+ jump_list *revertframes;+ jump_list *wordboundary;+ jump_list *anynewline;+ jump_list *hspace;+ jump_list *vspace;+ jump_list *casefulcmp;+ jump_list *caselesscmp;+ jump_list *reset_match;+ BOOL unset_backref;+ BOOL alt_circumflex;+#ifdef SUPPORT_UNICODE+ BOOL utf;+ BOOL invalid_utf;+ BOOL ucp;+ /* Points to saving area for iref. */+ sljit_s32 iref_ptr;+ jump_list *getucd;+ jump_list *getucdtype;+#if PCRE2_CODE_UNIT_WIDTH == 8+ jump_list *utfreadchar;+ jump_list *utfreadtype8;+ jump_list *utfpeakcharback;+#endif+#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16+ jump_list *utfreadchar_invalid;+ jump_list *utfreadnewline_invalid;+ jump_list *utfmoveback_invalid;+ jump_list *utfpeakcharback_invalid;+#endif+#endif /* SUPPORT_UNICODE */+} compiler_common;++/* For byte_sequence_compare. */++typedef struct compare_context {+ int length;+ int sourcereg;+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED+ int ucharptr;+ union {+ sljit_s32 asint;+ sljit_u16 asushort;+#if PCRE2_CODE_UNIT_WIDTH == 8+ sljit_u8 asbyte;+ sljit_u8 asuchars[4];+#elif PCRE2_CODE_UNIT_WIDTH == 16+ sljit_u16 asuchars[2];+#elif PCRE2_CODE_UNIT_WIDTH == 32+ sljit_u32 asuchars[1];+#endif+ } c;+ union {+ sljit_s32 asint;+ sljit_u16 asushort;+#if PCRE2_CODE_UNIT_WIDTH == 8+ sljit_u8 asbyte;+ sljit_u8 asuchars[4];+#elif PCRE2_CODE_UNIT_WIDTH == 16+ sljit_u16 asuchars[2];+#elif PCRE2_CODE_UNIT_WIDTH == 32+ sljit_u32 asuchars[1];+#endif+ } oc;+#endif+} compare_context;++/* Undefine sljit macros. */+#undef CMP++/* Used for accessing the elements of the stack. */+#define STACK(i) ((i) * (int)sizeof(sljit_sw))++#ifdef SLJIT_PREF_SHIFT_REG+#if SLJIT_PREF_SHIFT_REG == SLJIT_R2+/* Nothing. */+#elif SLJIT_PREF_SHIFT_REG == SLJIT_R3+#define SHIFT_REG_IS_R3+#else+#error "Unsupported shift register"+#endif+#endif++#define TMP1 SLJIT_R0+#ifdef SHIFT_REG_IS_R3+#define TMP2 SLJIT_R3+#define TMP3 SLJIT_R2+#else+#define TMP2 SLJIT_R2+#define TMP3 SLJIT_R3+#endif+#define STR_PTR SLJIT_R1+#define STR_END SLJIT_S0+#define STACK_TOP SLJIT_S1+#define STACK_LIMIT SLJIT_S2+#define COUNT_MATCH SLJIT_S3+#define ARGUMENTS SLJIT_S4+#define RETURN_ADDR SLJIT_R4++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+#define HAS_VIRTUAL_REGISTERS 1+#else+#define HAS_VIRTUAL_REGISTERS 0+#endif++/* Local space layout. */+/* These two locals can be used by the current opcode. */+#define LOCALS0 (0 * sizeof(sljit_sw))+#define LOCALS1 (1 * sizeof(sljit_sw))+/* Two local variables for possessive quantifiers (char1 cannot use them). */+#define POSSESSIVE0 (2 * sizeof(sljit_sw))+#define POSSESSIVE1 (3 * sizeof(sljit_sw))+/* Max limit of recursions. */+#define LIMIT_MATCH (4 * sizeof(sljit_sw))+/* The output vector is stored on the stack, and contains pointers+to characters. The vector data is divided into two groups: the first+group contains the start / end character pointers, and the second is+the start pointers when the end of the capturing group has not yet reached. */+#define OVECTOR_START (common->ovector_start)+#define OVECTOR(i) (OVECTOR_START + (i) * (sljit_sw)sizeof(sljit_sw))+#define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * (sljit_sw)sizeof(sljit_sw))+#define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start])++#if PCRE2_CODE_UNIT_WIDTH == 8+#define MOV_UCHAR SLJIT_MOV_U8+#define IN_UCHARS(x) (x)+#elif PCRE2_CODE_UNIT_WIDTH == 16+#define MOV_UCHAR SLJIT_MOV_U16+#define UCHAR_SHIFT (1)+#define IN_UCHARS(x) ((x) * 2)+#elif PCRE2_CODE_UNIT_WIDTH == 32+#define MOV_UCHAR SLJIT_MOV_U32+#define UCHAR_SHIFT (2)+#define IN_UCHARS(x) ((x) * 4)+#else+#error Unsupported compiling mode+#endif++/* Shortcuts. */+#define DEFINE_COMPILER \+ struct sljit_compiler *compiler = common->compiler+#define OP1(op, dst, dstw, src, srcw) \+ sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))+#define OP2(op, dst, dstw, src1, src1w, src2, src2w) \+ sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))+#define OP_SRC(op, src, srcw) \+ sljit_emit_op_src(compiler, (op), (src), (srcw))+#define LABEL() \+ sljit_emit_label(compiler)+#define JUMP(type) \+ sljit_emit_jump(compiler, (type))+#define JUMPTO(type, label) \+ sljit_set_label(sljit_emit_jump(compiler, (type)), (label))+#define JUMPHERE(jump) \+ sljit_set_label((jump), sljit_emit_label(compiler))+#define SET_LABEL(jump, label) \+ sljit_set_label((jump), (label))+#define CMP(type, src1, src1w, src2, src2w) \+ sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))+#define CMPTO(type, src1, src1w, src2, src2w, label) \+ sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))+#define OP_FLAGS(op, dst, dstw, type) \+ sljit_emit_op_flags(compiler, (op), (dst), (dstw), (type))+#define CMOV(type, dst_reg, src, srcw) \+ sljit_emit_cmov(compiler, (type), (dst_reg), (src), (srcw))+#define GET_LOCAL_BASE(dst, dstw, offset) \+ sljit_get_local_base(compiler, (dst), (dstw), (offset))++#define READ_CHAR_MAX 0x7fffffff++#define INVALID_UTF_CHAR -1+#define UNASSIGNED_UTF_CHAR 888++#if defined SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8++#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \+ { \+ if (ptr[0] <= 0x7f) \+ c = *ptr++; \+ else if (ptr + 1 < end && ptr[1] >= 0x80 && ptr[1] < 0xc0) \+ { \+ c = ptr[1] - 0x80; \+ \+ if (ptr[0] >= 0xc2 && ptr[0] <= 0xdf) \+ { \+ c |= (ptr[0] - 0xc0) << 6; \+ ptr += 2; \+ } \+ else if (ptr + 2 < end && ptr[2] >= 0x80 && ptr[2] < 0xc0) \+ { \+ c = c << 6 | (ptr[2] - 0x80); \+ \+ if (ptr[0] >= 0xe0 && ptr[0] <= 0xef) \+ { \+ c |= (ptr[0] - 0xe0) << 12; \+ ptr += 3; \+ \+ if (c < 0x800 || (c >= 0xd800 && c < 0xe000)) \+ { \+ invalid_action; \+ } \+ } \+ else if (ptr + 3 < end && ptr[3] >= 0x80 && ptr[3] < 0xc0) \+ { \+ c = c << 6 | (ptr[3] - 0x80); \+ \+ if (ptr[0] >= 0xf0 && ptr[0] <= 0xf4) \+ { \+ c |= (ptr[0] - 0xf0) << 18; \+ ptr += 4; \+ \+ if (c >= 0x110000 || c < 0x10000) \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ }++#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \+ { \+ c = ptr[-1]; \+ if (c <= 0x7f) \+ ptr--; \+ else if (ptr - 1 > start && ptr[-1] >= 0x80 && ptr[-1] < 0xc0) \+ { \+ c -= 0x80; \+ \+ if (ptr[-2] >= 0xc2 && ptr[-2] <= 0xdf) \+ { \+ c |= (ptr[-2] - 0xc0) << 6; \+ ptr -= 2; \+ } \+ else if (ptr - 2 > start && ptr[-2] >= 0x80 && ptr[-2] < 0xc0) \+ { \+ c = c << 6 | (ptr[-2] - 0x80); \+ \+ if (ptr[-3] >= 0xe0 && ptr[-3] <= 0xef) \+ { \+ c |= (ptr[-3] - 0xe0) << 12; \+ ptr -= 3; \+ \+ if (c < 0x800 || (c >= 0xd800 && c < 0xe000)) \+ { \+ invalid_action; \+ } \+ } \+ else if (ptr - 3 > start && ptr[-3] >= 0x80 && ptr[-3] < 0xc0) \+ { \+ c = c << 6 | (ptr[-3] - 0x80); \+ \+ if (ptr[-4] >= 0xf0 && ptr[-4] <= 0xf4) \+ { \+ c |= (ptr[-4] - 0xf0) << 18; \+ ptr -= 4; \+ \+ if (c >= 0x110000 || c < 0x10000) \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ } \+ else \+ { \+ invalid_action; \+ } \+ }++#elif PCRE2_CODE_UNIT_WIDTH == 16++#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \+ { \+ if (ptr[0] < 0xd800 || ptr[0] >= 0xe000) \+ c = *ptr++; \+ else if (ptr[0] < 0xdc00 && ptr + 1 < end && ptr[1] >= 0xdc00 && ptr[1] < 0xe000) \+ { \+ c = (((ptr[0] - 0xd800) << 10) | (ptr[1] - 0xdc00)) + 0x10000; \+ ptr += 2; \+ } \+ else \+ { \+ invalid_action; \+ } \+ }++#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \+ { \+ c = ptr[-1]; \+ if (c < 0xd800 || c >= 0xe000) \+ ptr--; \+ else if (c >= 0xdc00 && ptr - 1 > start && ptr[-2] >= 0xd800 && ptr[-2] < 0xdc00) \+ { \+ c = (((ptr[-2] - 0xd800) << 10) | (c - 0xdc00)) + 0x10000; \+ ptr -= 2; \+ } \+ else \+ { \+ invalid_action; \+ } \+ }+++#elif PCRE2_CODE_UNIT_WIDTH == 32++#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \+ { \+ if (ptr[0] < 0xd800 || (ptr[0] >= 0xe000 && ptr[0] < 0x110000)) \+ c = *ptr++; \+ else \+ { \+ invalid_action; \+ } \+ }++#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \+ { \+ c = ptr[-1]; \+ if (ptr[-1] < 0xd800 || (ptr[-1] >= 0xe000 && ptr[-1] < 0x110000)) \+ ptr--; \+ else \+ { \+ invalid_action; \+ } \+ }++#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+#endif /* SUPPORT_UNICODE */++static PCRE2_SPTR bracketend(PCRE2_SPTR cc)+{+SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND));+do cc += GET(cc, 1); while (*cc == OP_ALT);+SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);+cc += 1 + LINK_SIZE;+return cc;+}++static int no_alternatives(PCRE2_SPTR cc)+{+int count = 0;+SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND));+do+ {+ cc += GET(cc, 1);+ count++;+ }+while (*cc == OP_ALT);+SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);+return count;+}++/* Functions whose might need modification for all new supported opcodes:+ next_opcode+ check_opcode_types+ set_private_data_ptrs+ get_framesize+ init_frame+ get_recurse_data_length+ copy_recurse_data+ compile_matchingpath+ compile_backtrackingpath+*/++static PCRE2_SPTR next_opcode(compiler_common *common, PCRE2_SPTR cc)+{+SLJIT_UNUSED_ARG(common);+switch(*cc)+ {+ case OP_SOD:+ case OP_SOM:+ case OP_SET_SOM:+ case OP_NOT_WORD_BOUNDARY:+ case OP_WORD_BOUNDARY:+ case OP_NOT_DIGIT:+ case OP_DIGIT:+ case OP_NOT_WHITESPACE:+ case OP_WHITESPACE:+ case OP_NOT_WORDCHAR:+ case OP_WORDCHAR:+ case OP_ANY:+ case OP_ALLANY:+ case OP_NOTPROP:+ case OP_PROP:+ case OP_ANYNL:+ case OP_NOT_HSPACE:+ case OP_HSPACE:+ case OP_NOT_VSPACE:+ case OP_VSPACE:+ case OP_EXTUNI:+ case OP_EODN:+ case OP_EOD:+ case OP_CIRC:+ case OP_CIRCM:+ case OP_DOLL:+ case OP_DOLLM:+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRPLUS:+ case OP_CRMINPLUS:+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSSTAR:+ case OP_CRPOSPLUS:+ case OP_CRPOSQUERY:+ case OP_CRPOSRANGE:+ case OP_CLASS:+ case OP_NCLASS:+ case OP_REF:+ case OP_REFI:+ case OP_DNREF:+ case OP_DNREFI:+ case OP_RECURSE:+ case OP_CALLOUT:+ case OP_ALT:+ case OP_KET:+ case OP_KETRMAX:+ case OP_KETRMIN:+ case OP_KETRPOS:+ case OP_REVERSE:+ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRA:+ case OP_BRAPOS:+ case OP_CBRA:+ case OP_CBRAPOS:+ case OP_COND:+ case OP_SBRA:+ case OP_SBRAPOS:+ case OP_SCBRA:+ case OP_SCBRAPOS:+ case OP_SCOND:+ case OP_CREF:+ case OP_DNCREF:+ case OP_RREF:+ case OP_DNRREF:+ case OP_FALSE:+ case OP_TRUE:+ case OP_BRAZERO:+ case OP_BRAMINZERO:+ case OP_BRAPOSZERO:+ case OP_PRUNE:+ case OP_SKIP:+ case OP_THEN:+ case OP_COMMIT:+ case OP_FAIL:+ case OP_ACCEPT:+ case OP_ASSERT_ACCEPT:+ case OP_CLOSE:+ case OP_SKIPZERO:+ return cc + PRIV(OP_lengths)[*cc];++ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ case OP_STAR:+ case OP_MINSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSPLUS:+ case OP_POSQUERY:+ case OP_POSUPTO:+ case OP_STARI:+ case OP_MINSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_EXACTI:+ case OP_POSSTARI:+ case OP_POSPLUSI:+ case OP_POSQUERYI:+ case OP_POSUPTOI:+ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTEXACT:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSUPTO:+ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTEXACTI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSUPTOI:+ cc += PRIV(OP_lengths)[*cc];+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ return cc;++ /* Special cases. */+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ case OP_TYPEPOSUPTO:+ return cc + PRIV(OP_lengths)[*cc] - 1;++ case OP_ANYBYTE:+#ifdef SUPPORT_UNICODE+ if (common->utf) return NULL;+#endif+ return cc + 1;++ case OP_CALLOUT_STR:+ return cc + GET(cc, 1 + 2*LINK_SIZE);++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ return cc + GET(cc, 1);+#endif++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ return cc + 1 + 2 + cc[1];++ default:+ SLJIT_UNREACHABLE();+ return NULL;+ }+}++static BOOL check_opcode_types(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend)+{+int count;+PCRE2_SPTR slot;+PCRE2_SPTR assert_back_end = cc - 1;+PCRE2_SPTR assert_na_end = cc - 1;++/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */+while (cc < ccend)+ {+ switch(*cc)+ {+ case OP_SET_SOM:+ common->has_set_som = TRUE;+ common->might_be_empty = TRUE;+ cc += 1;+ break;++ case OP_REFI:+#ifdef SUPPORT_UNICODE+ if (common->iref_ptr == 0)+ {+ common->iref_ptr = common->ovector_start;+ common->ovector_start += 3 * sizeof(sljit_sw);+ }+#endif /* SUPPORT_UNICODE */+ /* Fall through. */+ case OP_REF:+ common->optimized_cbracket[GET2(cc, 1)] = 0;+ cc += 1 + IMM2_SIZE;+ break;++ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ slot = bracketend(cc);+ if (slot > assert_na_end)+ assert_na_end = slot;+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;+ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_COND:+ case OP_SCOND:+ /* Only AUTO_CALLOUT can insert this opcode. We do+ not intend to support this case. */+ if (cc[1 + LINK_SIZE] == OP_CALLOUT || cc[1 + LINK_SIZE] == OP_CALLOUT_STR)+ return FALSE;+ cc += 1 + LINK_SIZE;+ break;++ case OP_CREF:+ common->optimized_cbracket[GET2(cc, 1)] = 0;+ cc += 1 + IMM2_SIZE;+ break;++ case OP_DNREF:+ case OP_DNREFI:+ case OP_DNCREF:+ count = GET2(cc, 1 + IMM2_SIZE);+ slot = common->name_table + GET2(cc, 1) * common->name_entry_size;+ while (count-- > 0)+ {+ common->optimized_cbracket[GET2(slot, 0)] = 0;+ slot += common->name_entry_size;+ }+ cc += 1 + 2 * IMM2_SIZE;+ break;++ case OP_RECURSE:+ /* Set its value only once. */+ if (common->recursive_head_ptr == 0)+ {+ common->recursive_head_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_CALLOUT:+ case OP_CALLOUT_STR:+ if (common->capture_last_ptr == 0)+ {+ common->capture_last_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+ cc += (*cc == OP_CALLOUT) ? PRIV(OP_lengths)[OP_CALLOUT] : GET(cc, 1 + 2*LINK_SIZE);+ break;++ case OP_ASSERTBACK:+ slot = bracketend(cc);+ if (slot > assert_back_end)+ assert_back_end = slot;+ cc += 1 + LINK_SIZE;+ break;++ case OP_THEN_ARG:+ common->has_then = TRUE;+ common->control_head_ptr = 1;+ /* Fall through. */++ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ if (cc < assert_na_end)+ return FALSE;+ /* Fall through */+ case OP_MARK:+ if (common->mark_ptr == 0)+ {+ common->mark_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+ cc += 1 + 2 + cc[1];+ break;++ case OP_THEN:+ common->has_then = TRUE;+ common->control_head_ptr = 1;+ cc += 1;+ break;++ case OP_SKIP:+ if (cc < assert_back_end)+ common->has_skip_in_assert_back = TRUE;+ if (cc < assert_na_end)+ return FALSE;+ cc += 1;+ break;++ case OP_SKIP_ARG:+ common->control_head_ptr = 1;+ common->has_skip_arg = TRUE;+ if (cc < assert_back_end)+ common->has_skip_in_assert_back = TRUE;+ if (cc < assert_na_end)+ return FALSE;+ cc += 1 + 2 + cc[1];+ break;++ case OP_PRUNE:+ case OP_COMMIT:+ case OP_ASSERT_ACCEPT:+ if (cc < assert_na_end)+ return FALSE;+ cc++;+ break;++ default:+ cc = next_opcode(common, cc);+ if (cc == NULL)+ return FALSE;+ break;+ }+ }+return TRUE;+}++#define EARLY_FAIL_ENHANCE_MAX (1 + 1)++/*+start:+ 0 - skip / early fail allowed+ 1 - only early fail with range allowed+ >1 - (start - 1) early fail is processed++return: current number of iterators enhanced with fast fail+*/+static int detect_early_fail(compiler_common *common, PCRE2_SPTR cc, int *private_data_start, sljit_s32 depth, int start)+{+PCRE2_SPTR next_alt;+PCRE2_SPTR end;+PCRE2_SPTR accelerated_start;+int result = 0;+int count;+BOOL fast_forward_allowed = TRUE;++SLJIT_ASSERT(*cc == OP_ONCE || *cc == OP_BRA || *cc == OP_CBRA);+SLJIT_ASSERT(*cc != OP_CBRA || common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] != 0);+SLJIT_ASSERT(start < EARLY_FAIL_ENHANCE_MAX);++do+ {+ count = start;+ next_alt = cc + GET(cc, 1);+ cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0);++ while (TRUE)+ {+ accelerated_start = NULL;++ switch(*cc)+ {+ case OP_SOD:+ case OP_SOM:+ case OP_SET_SOM:+ case OP_NOT_WORD_BOUNDARY:+ case OP_WORD_BOUNDARY:+ case OP_EODN:+ case OP_EOD:+ case OP_CIRC:+ case OP_CIRCM:+ case OP_DOLL:+ case OP_DOLLM:+ /* Zero width assertions. */+ cc++;+ continue;++ case OP_NOT_DIGIT:+ case OP_DIGIT:+ case OP_NOT_WHITESPACE:+ case OP_WHITESPACE:+ case OP_NOT_WORDCHAR:+ case OP_WORDCHAR:+ case OP_ANY:+ case OP_ALLANY:+ case OP_ANYBYTE:+ case OP_NOT_HSPACE:+ case OP_HSPACE:+ case OP_NOT_VSPACE:+ case OP_VSPACE:+ fast_forward_allowed = FALSE;+ cc++;+ continue;++ case OP_ANYNL:+ case OP_EXTUNI:+ fast_forward_allowed = FALSE;+ if (count == 0)+ count = 1;+ cc++;+ continue;++ case OP_NOTPROP:+ case OP_PROP:+ fast_forward_allowed = FALSE;+ cc += 1 + 2;+ continue;++ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ fast_forward_allowed = FALSE;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ continue;++ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ /* The type or prop opcode is skipped in the next iteration. */+ cc += 1;++ if (cc[0] != OP_ANYNL && cc[0] != OP_EXTUNI)+ {+ accelerated_start = cc - 1;+ break;+ }++ if (count == 0)+ count = 1;+ fast_forward_allowed = FALSE;+ continue;++ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ case OP_TYPEPOSUPTO:+ cc += IMM2_SIZE;+ /* Fall through */++ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSQUERY:+ /* The type or prop opcode is skipped in the next iteration. */+ fast_forward_allowed = FALSE;+ if (count == 0)+ count = 1;+ cc += 1;+ continue;++ case OP_STAR:+ case OP_MINSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_POSSTAR:+ case OP_POSPLUS:++ case OP_STARI:+ case OP_MINSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_POSSTARI:+ case OP_POSPLUSI:++ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:++ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ accelerated_start = cc;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ case OP_UPTO:+ case OP_MINUPTO:+ case OP_EXACT:+ case OP_POSUPTO:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_EXACTI:+ case OP_POSUPTOI:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTEXACT:+ case OP_NOTPOSUPTO:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTEXACTI:+ case OP_NOTPOSUPTOI:+ cc += IMM2_SIZE;+ /* Fall through */++ case OP_QUERY:+ case OP_MINQUERY:+ case OP_POSQUERY:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_POSQUERYI:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTPOSQUERY:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTPOSQUERYI:+ fast_forward_allowed = FALSE;+ if (count == 0)+ count = 1;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ continue;++ case OP_CLASS:+ case OP_NCLASS:+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ accelerated_start = cc;+ cc += ((*cc == OP_XCLASS) ? GET(cc, 1) : (unsigned int)(1 + (32 / sizeof(PCRE2_UCHAR))));+#else+ accelerated_start = cc;+ cc += (1 + (32 / sizeof(PCRE2_UCHAR)));+#endif++ switch (*cc)+ {+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRPLUS:+ case OP_CRMINPLUS:+ case OP_CRPOSSTAR:+ case OP_CRPOSPLUS:+ cc++;+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ cc += 2 * IMM2_SIZE;+ /* Fall through */+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSQUERY:+ cc++;+ if (count == 0)+ count = 1;+ /* Fall through */+ default:+ accelerated_start = NULL;+ fast_forward_allowed = FALSE;+ continue;+ }+ break;++ case OP_ONCE:+ case OP_BRA:+ case OP_CBRA:+ end = cc + GET(cc, 1);++ if (*end == OP_KET && PRIVATE_DATA(end) == 0)+ {+ if (*cc == OP_CBRA)+ {+ if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)+ break;+ cc += IMM2_SIZE;+ }++ cc += 1 + LINK_SIZE;+ continue;+ }++ fast_forward_allowed = FALSE;+ if (depth >= 4)+ break;++ end = bracketend(cc) - (1 + LINK_SIZE);+ if (*end != OP_KET || PRIVATE_DATA(end) != 0)+ break;++ if (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)+ break;++ count = detect_early_fail(common, cc, private_data_start, depth + 1, count);+ if (count < EARLY_FAIL_ENHANCE_MAX)+ {+ cc = end + (1 + LINK_SIZE);+ continue;+ }+ break;++ case OP_KET:+ SLJIT_ASSERT(PRIVATE_DATA(cc) == 0);+ if (cc >= next_alt)+ break;+ cc += 1 + LINK_SIZE;+ continue;+ }++ if (accelerated_start != NULL)+ {+ if (count == 0)+ {+ count++;++ if (fast_forward_allowed && *next_alt == OP_KET)+ {+ common->fast_forward_bc_ptr = accelerated_start;+ common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_skip;+ *private_data_start += sizeof(sljit_sw);+ }+ else+ {+ common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_fail;++ if (common->early_fail_start_ptr == 0)+ common->early_fail_start_ptr = *private_data_start;++ *private_data_start += sizeof(sljit_sw);+ common->early_fail_end_ptr = *private_data_start;++ if (*private_data_start > SLJIT_MAX_LOCAL_SIZE)+ return EARLY_FAIL_ENHANCE_MAX;+ }+ }+ else+ {+ common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_fail_range;++ if (common->early_fail_start_ptr == 0)+ common->early_fail_start_ptr = *private_data_start;++ *private_data_start += 2 * sizeof(sljit_sw);+ common->early_fail_end_ptr = *private_data_start;++ if (*private_data_start > SLJIT_MAX_LOCAL_SIZE)+ return EARLY_FAIL_ENHANCE_MAX;+ }++ count++;++ if (count < EARLY_FAIL_ENHANCE_MAX)+ continue;+ }++ break;+ }++ if (*cc != OP_ALT && *cc != OP_KET)+ result = EARLY_FAIL_ENHANCE_MAX;+ else if (result < count)+ result = count;++ fast_forward_allowed = FALSE;+ cc = next_alt;+ }+while (*cc == OP_ALT);++return result;+}++static int get_class_iterator_size(PCRE2_SPTR cc)+{+sljit_u32 min;+sljit_u32 max;+switch(*cc)+ {+ case OP_CRSTAR:+ case OP_CRPLUS:+ return 2;++ case OP_CRMINSTAR:+ case OP_CRMINPLUS:+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ return 1;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ min = GET2(cc, 1);+ max = GET2(cc, 1 + IMM2_SIZE);+ if (max == 0)+ return (*cc == OP_CRRANGE) ? 2 : 1;+ max -= min;+ if (max > 2)+ max = 2;+ return max;++ default:+ return 0;+ }+}++static BOOL detect_repeat(compiler_common *common, PCRE2_SPTR begin)+{+PCRE2_SPTR end = bracketend(begin);+PCRE2_SPTR next;+PCRE2_SPTR next_end;+PCRE2_SPTR max_end;+PCRE2_UCHAR type;+sljit_sw length = end - begin;+sljit_s32 min, max, i;++/* Detect fixed iterations first. */+if (end[-(1 + LINK_SIZE)] != OP_KET)+ return FALSE;++/* Already detected repeat. */+if (common->private_data_ptrs[end - common->start - LINK_SIZE] != 0)+ return TRUE;++next = end;+min = 1;+while (1)+ {+ if (*next != *begin)+ break;+ next_end = bracketend(next);+ if (next_end - next != length || memcmp(begin, next, IN_UCHARS(length)) != 0)+ break;+ next = next_end;+ min++;+ }++if (min == 2)+ return FALSE;++max = 0;+max_end = next;+if (*next == OP_BRAZERO || *next == OP_BRAMINZERO)+ {+ type = *next;+ while (1)+ {+ if (next[0] != type || next[1] != OP_BRA || next[2 + LINK_SIZE] != *begin)+ break;+ next_end = bracketend(next + 2 + LINK_SIZE);+ if (next_end - next != (length + 2 + LINK_SIZE) || memcmp(begin, next + 2 + LINK_SIZE, IN_UCHARS(length)) != 0)+ break;+ next = next_end;+ max++;+ }++ if (next[0] == type && next[1] == *begin && max >= 1)+ {+ next_end = bracketend(next + 1);+ if (next_end - next == (length + 1) && memcmp(begin, next + 1, IN_UCHARS(length)) == 0)+ {+ for (i = 0; i < max; i++, next_end += 1 + LINK_SIZE)+ if (*next_end != OP_KET)+ break;++ if (i == max)+ {+ common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end;+ common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO;+ /* +2 the original and the last. */+ common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2;+ if (min == 1)+ return TRUE;+ min--;+ max_end -= (1 + LINK_SIZE) + GET(max_end, -LINK_SIZE);+ }+ }+ }+ }++if (min >= 3)+ {+ common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end;+ common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT;+ common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min;+ return TRUE;+ }++return FALSE;+}++#define CASE_ITERATOR_PRIVATE_DATA_1 \+ case OP_MINSTAR: \+ case OP_MINPLUS: \+ case OP_QUERY: \+ case OP_MINQUERY: \+ case OP_MINSTARI: \+ case OP_MINPLUSI: \+ case OP_QUERYI: \+ case OP_MINQUERYI: \+ case OP_NOTMINSTAR: \+ case OP_NOTMINPLUS: \+ case OP_NOTQUERY: \+ case OP_NOTMINQUERY: \+ case OP_NOTMINSTARI: \+ case OP_NOTMINPLUSI: \+ case OP_NOTQUERYI: \+ case OP_NOTMINQUERYI:++#define CASE_ITERATOR_PRIVATE_DATA_2A \+ case OP_STAR: \+ case OP_PLUS: \+ case OP_STARI: \+ case OP_PLUSI: \+ case OP_NOTSTAR: \+ case OP_NOTPLUS: \+ case OP_NOTSTARI: \+ case OP_NOTPLUSI:++#define CASE_ITERATOR_PRIVATE_DATA_2B \+ case OP_UPTO: \+ case OP_MINUPTO: \+ case OP_UPTOI: \+ case OP_MINUPTOI: \+ case OP_NOTUPTO: \+ case OP_NOTMINUPTO: \+ case OP_NOTUPTOI: \+ case OP_NOTMINUPTOI:++#define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \+ case OP_TYPEMINSTAR: \+ case OP_TYPEMINPLUS: \+ case OP_TYPEQUERY: \+ case OP_TYPEMINQUERY:++#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \+ case OP_TYPESTAR: \+ case OP_TYPEPLUS:++#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \+ case OP_TYPEUPTO: \+ case OP_TYPEMINUPTO:++static void set_private_data_ptrs(compiler_common *common, int *private_data_start, PCRE2_SPTR ccend)+{+PCRE2_SPTR cc = common->start;+PCRE2_SPTR alternative;+PCRE2_SPTR end = NULL;+int private_data_ptr = *private_data_start;+int space, size, bracketlen;+BOOL repeat_check = TRUE;++while (cc < ccend)+ {+ space = 0;+ size = 0;+ bracketlen = 0;+ if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE)+ break;++ if (repeat_check && (*cc == OP_ONCE || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND))+ {+ if (detect_repeat(common, cc))+ {+ /* These brackets are converted to repeats, so no global+ based single character repeat is allowed. */+ if (cc >= end)+ end = bracketend(cc);+ }+ }+ repeat_check = TRUE;++ switch(*cc)+ {+ case OP_KET:+ if (common->private_data_ptrs[cc + 1 - common->start] != 0)+ {+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw);+ cc += common->private_data_ptrs[cc + 1 - common->start];+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRAPOS:+ case OP_SBRA:+ case OP_SBRAPOS:+ case OP_SCOND:+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw);+ bracketlen = 1 + LINK_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw);+ bracketlen = 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_COND:+ /* Might be a hidden SCOND. */+ alternative = cc + GET(cc, 1);+ if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)+ {+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw);+ }+ bracketlen = 1 + LINK_SIZE;+ break;++ case OP_BRA:+ bracketlen = 1 + LINK_SIZE;+ break;++ case OP_CBRA:+ case OP_SCBRA:+ bracketlen = 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_BRAZERO:+ case OP_BRAMINZERO:+ case OP_BRAPOSZERO:+ size = 1;+ repeat_check = FALSE;+ break;++ CASE_ITERATOR_PRIVATE_DATA_1+ size = -2;+ space = 1;+ break;++ CASE_ITERATOR_PRIVATE_DATA_2A+ size = -2;+ space = 2;+ break;++ CASE_ITERATOR_PRIVATE_DATA_2B+ size = -(2 + IMM2_SIZE);+ space = 2;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_1+ size = 1;+ space = 1;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_2A+ size = 1;+ if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI)+ space = 2;+ break;++ case OP_TYPEUPTO:+ size = 1 + IMM2_SIZE;+ if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI)+ space = 2;+ break;++ case OP_TYPEMINUPTO:+ size = 1 + IMM2_SIZE;+ space = 2;+ break;++ case OP_CLASS:+ case OP_NCLASS:+ size = 1 + 32 / sizeof(PCRE2_UCHAR);+ space = get_class_iterator_size(cc + size);+ break;++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ size = GET(cc, 1);+ space = get_class_iterator_size(cc + size);+ break;+#endif++ default:+ cc = next_opcode(common, cc);+ SLJIT_ASSERT(cc != NULL);+ break;+ }++ /* Character iterators, which are not inside a repeated bracket,+ gets a private slot instead of allocating it on the stack. */+ if (space > 0 && cc >= end)+ {+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += sizeof(sljit_sw) * space;+ }++ if (size != 0)+ {+ if (size < 0)+ {+ cc += -size;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ }+ else+ cc += size;+ }++ if (bracketlen > 0)+ {+ if (cc >= end)+ {+ end = bracketend(cc);+ if (end[-1 - LINK_SIZE] == OP_KET)+ end = NULL;+ }+ cc += bracketlen;+ }+ }+*private_data_start = private_data_ptr;+}++/* Returns with a frame_types (always < 0) if no need for frame. */+static int get_framesize(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, BOOL recursive, BOOL *needs_control_head)+{+int length = 0;+int possessive = 0;+BOOL stack_restore = FALSE;+BOOL setsom_found = recursive;+BOOL setmark_found = recursive;+/* The last capture is a local variable even for recursions. */+BOOL capture_last_found = FALSE;++#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD+SLJIT_ASSERT(common->control_head_ptr != 0);+*needs_control_head = TRUE;+#else+*needs_control_head = FALSE;+#endif++if (ccend == NULL)+ {+ ccend = bracketend(cc) - (1 + LINK_SIZE);+ if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))+ {+ possessive = length = (common->capture_last_ptr != 0) ? 5 : 3;+ /* This is correct regardless of common->capture_last_ptr. */+ capture_last_found = TRUE;+ }+ cc = next_opcode(common, cc);+ }++SLJIT_ASSERT(cc != NULL);+while (cc < ccend)+ switch(*cc)+ {+ case OP_SET_SOM:+ SLJIT_ASSERT(common->has_set_som);+ stack_restore = TRUE;+ if (!setsom_found)+ {+ length += 2;+ setsom_found = TRUE;+ }+ cc += 1;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_THEN_ARG:+ SLJIT_ASSERT(common->mark_ptr != 0);+ stack_restore = TRUE;+ if (!setmark_found)+ {+ length += 2;+ setmark_found = TRUE;+ }+ if (common->control_head_ptr != 0)+ *needs_control_head = TRUE;+ cc += 1 + 2 + cc[1];+ break;++ case OP_RECURSE:+ stack_restore = TRUE;+ if (common->has_set_som && !setsom_found)+ {+ length += 2;+ setsom_found = TRUE;+ }+ if (common->mark_ptr != 0 && !setmark_found)+ {+ length += 2;+ setmark_found = TRUE;+ }+ if (common->capture_last_ptr != 0 && !capture_last_found)+ {+ length += 2;+ capture_last_found = TRUE;+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRA:+ case OP_CBRAPOS:+ case OP_SCBRA:+ case OP_SCBRAPOS:+ stack_restore = TRUE;+ if (common->capture_last_ptr != 0 && !capture_last_found)+ {+ length += 2;+ capture_last_found = TRUE;+ }+ length += 3;+ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_THEN:+ stack_restore = TRUE;+ if (common->control_head_ptr != 0)+ *needs_control_head = TRUE;+ cc ++;+ break;++ default:+ stack_restore = TRUE;+ /* Fall through. */++ case OP_NOT_WORD_BOUNDARY:+ case OP_WORD_BOUNDARY:+ case OP_NOT_DIGIT:+ case OP_DIGIT:+ case OP_NOT_WHITESPACE:+ case OP_WHITESPACE:+ case OP_NOT_WORDCHAR:+ case OP_WORDCHAR:+ case OP_ANY:+ case OP_ALLANY:+ case OP_ANYBYTE:+ case OP_NOTPROP:+ case OP_PROP:+ case OP_ANYNL:+ case OP_NOT_HSPACE:+ case OP_HSPACE:+ case OP_NOT_VSPACE:+ case OP_VSPACE:+ case OP_EXTUNI:+ case OP_EODN:+ case OP_EOD:+ case OP_CIRC:+ case OP_CIRCM:+ case OP_DOLL:+ case OP_DOLLM:+ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:++ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSPLUS:+ case OP_POSQUERY:+ case OP_POSUPTO:++ case OP_EXACTI:+ case OP_POSSTARI:+ case OP_POSPLUSI:+ case OP_POSQUERYI:+ case OP_POSUPTOI:++ case OP_NOTEXACT:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSUPTO:++ case OP_NOTEXACTI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSUPTOI:++ case OP_TYPEEXACT:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ case OP_TYPEPOSUPTO:++ case OP_CLASS:+ case OP_NCLASS:+ case OP_XCLASS:++ case OP_CALLOUT:+ case OP_CALLOUT_STR:++ cc = next_opcode(common, cc);+ SLJIT_ASSERT(cc != NULL);+ break;+ }++/* Possessive quantifiers can use a special case. */+if (SLJIT_UNLIKELY(possessive == length))+ return stack_restore ? no_frame : no_stack;++if (length > 0)+ return length + 1;+return stack_restore ? no_frame : no_stack;+}++static void init_frame(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, int stackpos, int stacktop)+{+DEFINE_COMPILER;+BOOL setsom_found = FALSE;+BOOL setmark_found = FALSE;+/* The last capture is a local variable even for recursions. */+BOOL capture_last_found = FALSE;+int offset;++/* >= 1 + shortest item size (2) */+SLJIT_UNUSED_ARG(stacktop);+SLJIT_ASSERT(stackpos >= stacktop + 2);++stackpos = STACK(stackpos);+if (ccend == NULL)+ {+ ccend = bracketend(cc) - (1 + LINK_SIZE);+ if (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)+ cc = next_opcode(common, cc);+ }++SLJIT_ASSERT(cc != NULL);+while (cc < ccend)+ switch(*cc)+ {+ case OP_SET_SOM:+ SLJIT_ASSERT(common->has_set_som);+ if (!setsom_found)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));+ stackpos -= (int)sizeof(sljit_sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= (int)sizeof(sljit_sw);+ setsom_found = TRUE;+ }+ cc += 1;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_THEN_ARG:+ SLJIT_ASSERT(common->mark_ptr != 0);+ if (!setmark_found)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr);+ stackpos -= (int)sizeof(sljit_sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= (int)sizeof(sljit_sw);+ setmark_found = TRUE;+ }+ cc += 1 + 2 + cc[1];+ break;++ case OP_RECURSE:+ if (common->has_set_som && !setsom_found)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));+ stackpos -= (int)sizeof(sljit_sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= (int)sizeof(sljit_sw);+ setsom_found = TRUE;+ }+ if (common->mark_ptr != 0 && !setmark_found)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr);+ stackpos -= (int)sizeof(sljit_sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= (int)sizeof(sljit_sw);+ setmark_found = TRUE;+ }+ if (common->capture_last_ptr != 0 && !capture_last_found)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr);+ stackpos -= (int)sizeof(sljit_sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= (int)sizeof(sljit_sw);+ capture_last_found = TRUE;+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRA:+ case OP_CBRAPOS:+ case OP_SCBRA:+ case OP_SCBRAPOS:+ if (common->capture_last_ptr != 0 && !capture_last_found)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr);+ stackpos -= (int)sizeof(sljit_sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= (int)sizeof(sljit_sw);+ capture_last_found = TRUE;+ }+ offset = (GET2(cc, 1 + LINK_SIZE)) << 1;+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));+ stackpos -= (int)sizeof(sljit_sw);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);+ stackpos -= (int)sizeof(sljit_sw);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);+ stackpos -= (int)sizeof(sljit_sw);++ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ default:+ cc = next_opcode(common, cc);+ SLJIT_ASSERT(cc != NULL);+ break;+ }++OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, 0);+SLJIT_ASSERT(stackpos == STACK(stacktop));+}++#define RECURSE_TMP_REG_COUNT 3++typedef struct delayed_mem_copy_status {+ struct sljit_compiler *compiler;+ int store_bases[RECURSE_TMP_REG_COUNT];+ int store_offsets[RECURSE_TMP_REG_COUNT];+ int tmp_regs[RECURSE_TMP_REG_COUNT];+ int saved_tmp_regs[RECURSE_TMP_REG_COUNT];+ int next_tmp_reg;+} delayed_mem_copy_status;++static void delayed_mem_copy_init(delayed_mem_copy_status *status, compiler_common *common)+{+int i;++for (i = 0; i < RECURSE_TMP_REG_COUNT; i++)+ {+ SLJIT_ASSERT(status->tmp_regs[i] >= 0);+ SLJIT_ASSERT(sljit_get_register_index(status->saved_tmp_regs[i]) < 0 || status->tmp_regs[i] == status->saved_tmp_regs[i]);++ status->store_bases[i] = -1;+ }+status->next_tmp_reg = 0;+status->compiler = common->compiler;+}++static void delayed_mem_copy_move(delayed_mem_copy_status *status, int load_base, sljit_sw load_offset,+ int store_base, sljit_sw store_offset)+{+struct sljit_compiler *compiler = status->compiler;+int next_tmp_reg = status->next_tmp_reg;+int tmp_reg = status->tmp_regs[next_tmp_reg];++SLJIT_ASSERT(load_base > 0 && store_base > 0);++if (status->store_bases[next_tmp_reg] == -1)+ {+ /* Preserve virtual registers. */+ if (sljit_get_register_index(status->saved_tmp_regs[next_tmp_reg]) < 0)+ OP1(SLJIT_MOV, status->saved_tmp_regs[next_tmp_reg], 0, tmp_reg, 0);+ }+else+ OP1(SLJIT_MOV, SLJIT_MEM1(status->store_bases[next_tmp_reg]), status->store_offsets[next_tmp_reg], tmp_reg, 0);++OP1(SLJIT_MOV, tmp_reg, 0, SLJIT_MEM1(load_base), load_offset);+status->store_bases[next_tmp_reg] = store_base;+status->store_offsets[next_tmp_reg] = store_offset;++status->next_tmp_reg = (next_tmp_reg + 1) % RECURSE_TMP_REG_COUNT;+}++static void delayed_mem_copy_finish(delayed_mem_copy_status *status)+{+struct sljit_compiler *compiler = status->compiler;+int next_tmp_reg = status->next_tmp_reg;+int tmp_reg, saved_tmp_reg, i;++for (i = 0; i < RECURSE_TMP_REG_COUNT; i++)+ {+ if (status->store_bases[next_tmp_reg] != -1)+ {+ tmp_reg = status->tmp_regs[next_tmp_reg];+ saved_tmp_reg = status->saved_tmp_regs[next_tmp_reg];++ OP1(SLJIT_MOV, SLJIT_MEM1(status->store_bases[next_tmp_reg]), status->store_offsets[next_tmp_reg], tmp_reg, 0);++ /* Restore virtual registers. */+ if (sljit_get_register_index(saved_tmp_reg) < 0)+ OP1(SLJIT_MOV, tmp_reg, 0, saved_tmp_reg, 0);+ }++ next_tmp_reg = (next_tmp_reg + 1) % RECURSE_TMP_REG_COUNT;+ }+}++#undef RECURSE_TMP_REG_COUNT++static int get_recurse_data_length(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend,+ BOOL *needs_control_head, BOOL *has_quit, BOOL *has_accept)+{+int length = 1;+int size;+PCRE2_SPTR alternative;+BOOL quit_found = FALSE;+BOOL accept_found = FALSE;+BOOL setsom_found = FALSE;+BOOL setmark_found = FALSE;+BOOL capture_last_found = FALSE;+BOOL control_head_found = FALSE;++#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD+SLJIT_ASSERT(common->control_head_ptr != 0);+control_head_found = TRUE;+#endif++/* Calculate the sum of the private machine words. */+while (cc < ccend)+ {+ size = 0;+ switch(*cc)+ {+ case OP_SET_SOM:+ SLJIT_ASSERT(common->has_set_som);+ setsom_found = TRUE;+ cc += 1;+ break;++ case OP_RECURSE:+ if (common->has_set_som)+ setsom_found = TRUE;+ if (common->mark_ptr != 0)+ setmark_found = TRUE;+ if (common->capture_last_ptr != 0)+ capture_last_found = TRUE;+ cc += 1 + LINK_SIZE;+ break;++ case OP_KET:+ if (PRIVATE_DATA(cc) != 0)+ {+ length++;+ SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);+ cc += PRIVATE_DATA(cc + 1);+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRAPOS:+ case OP_SBRA:+ case OP_SBRAPOS:+ case OP_SCOND:+ length++;+ SLJIT_ASSERT(PRIVATE_DATA(cc) != 0);+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRA:+ case OP_SCBRA:+ length += 2;+ if (common->capture_last_ptr != 0)+ capture_last_found = TRUE;+ if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)+ length++;+ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ length += 2 + 2;+ if (common->capture_last_ptr != 0)+ capture_last_found = TRUE;+ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_COND:+ /* Might be a hidden SCOND. */+ alternative = cc + GET(cc, 1);+ if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)+ length++;+ cc += 1 + LINK_SIZE;+ break;++ CASE_ITERATOR_PRIVATE_DATA_1+ if (PRIVATE_DATA(cc) != 0)+ length++;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_PRIVATE_DATA_2A+ if (PRIVATE_DATA(cc) != 0)+ length += 2;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_PRIVATE_DATA_2B+ if (PRIVATE_DATA(cc) != 0)+ length += 2;+ cc += 2 + IMM2_SIZE;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_1+ if (PRIVATE_DATA(cc) != 0)+ length++;+ cc += 1;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_2A+ if (PRIVATE_DATA(cc) != 0)+ length += 2;+ cc += 1;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_2B+ if (PRIVATE_DATA(cc) != 0)+ length += 2;+ cc += 1 + IMM2_SIZE;+ break;++ case OP_CLASS:+ case OP_NCLASS:+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR);+#else+ size = 1 + 32 / (int)sizeof(PCRE2_UCHAR);+#endif+ if (PRIVATE_DATA(cc) != 0)+ length += get_class_iterator_size(cc + size);+ cc += size;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_THEN_ARG:+ SLJIT_ASSERT(common->mark_ptr != 0);+ if (!setmark_found)+ setmark_found = TRUE;+ if (common->control_head_ptr != 0)+ control_head_found = TRUE;+ if (*cc != OP_MARK)+ quit_found = TRUE;++ cc += 1 + 2 + cc[1];+ break;++ case OP_PRUNE:+ case OP_SKIP:+ case OP_COMMIT:+ quit_found = TRUE;+ cc++;+ break;++ case OP_SKIP_ARG:+ quit_found = TRUE;+ cc += 1 + 2 + cc[1];+ break;++ case OP_THEN:+ SLJIT_ASSERT(common->control_head_ptr != 0);+ quit_found = TRUE;+ if (!control_head_found)+ control_head_found = TRUE;+ cc++;+ break;++ case OP_ACCEPT:+ case OP_ASSERT_ACCEPT:+ accept_found = TRUE;+ cc++;+ break;++ default:+ cc = next_opcode(common, cc);+ SLJIT_ASSERT(cc != NULL);+ break;+ }+ }+SLJIT_ASSERT(cc == ccend);++if (control_head_found)+ length++;+if (capture_last_found)+ length++;+if (quit_found)+ {+ if (setsom_found)+ length++;+ if (setmark_found)+ length++;+ }++*needs_control_head = control_head_found;+*has_quit = quit_found;+*has_accept = accept_found;+return length;+}++enum copy_recurse_data_types {+ recurse_copy_from_global,+ recurse_copy_private_to_global,+ recurse_copy_shared_to_global,+ recurse_copy_kept_shared_to_global,+ recurse_swap_global+};++static void copy_recurse_data(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend,+ int type, int stackptr, int stacktop, BOOL has_quit)+{+delayed_mem_copy_status status;+PCRE2_SPTR alternative;+sljit_sw private_srcw[2];+sljit_sw shared_srcw[3];+sljit_sw kept_shared_srcw[2];+int private_count, shared_count, kept_shared_count;+int from_sp, base_reg, offset, i;+BOOL setsom_found = FALSE;+BOOL setmark_found = FALSE;+BOOL capture_last_found = FALSE;+BOOL control_head_found = FALSE;++#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD+SLJIT_ASSERT(common->control_head_ptr != 0);+control_head_found = TRUE;+#endif++switch (type)+ {+ case recurse_copy_from_global:+ from_sp = TRUE;+ base_reg = STACK_TOP;+ break;++ case recurse_copy_private_to_global:+ case recurse_copy_shared_to_global:+ case recurse_copy_kept_shared_to_global:+ from_sp = FALSE;+ base_reg = STACK_TOP;+ break;++ default:+ SLJIT_ASSERT(type == recurse_swap_global);+ from_sp = FALSE;+ base_reg = TMP2;+ break;+ }++stackptr = STACK(stackptr);+stacktop = STACK(stacktop);++status.tmp_regs[0] = TMP1;+status.saved_tmp_regs[0] = TMP1;++if (base_reg != TMP2)+ {+ status.tmp_regs[1] = TMP2;+ status.saved_tmp_regs[1] = TMP2;+ }+else+ {+ status.saved_tmp_regs[1] = RETURN_ADDR;+ if (HAS_VIRTUAL_REGISTERS)+ status.tmp_regs[1] = STR_PTR;+ else+ status.tmp_regs[1] = RETURN_ADDR;+ }++status.saved_tmp_regs[2] = TMP3;+if (HAS_VIRTUAL_REGISTERS)+ status.tmp_regs[2] = STR_END;+else+ status.tmp_regs[2] = TMP3;++delayed_mem_copy_init(&status, common);++if (type != recurse_copy_shared_to_global && type != recurse_copy_kept_shared_to_global)+ {+ SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_private_to_global || type == recurse_swap_global);++ if (!from_sp)+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, common->recursive_head_ptr);++ if (from_sp || type == recurse_swap_global)+ delayed_mem_copy_move(&status, SLJIT_SP, common->recursive_head_ptr, base_reg, stackptr);+ }++stackptr += sizeof(sljit_sw);++#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD+if (type != recurse_copy_shared_to_global)+ {+ if (!from_sp)+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, common->control_head_ptr);++ if (from_sp || type == recurse_swap_global)+ delayed_mem_copy_move(&status, SLJIT_SP, common->control_head_ptr, base_reg, stackptr);+ }++stackptr += sizeof(sljit_sw);+#endif++while (cc < ccend)+ {+ private_count = 0;+ shared_count = 0;+ kept_shared_count = 0;++ switch(*cc)+ {+ case OP_SET_SOM:+ SLJIT_ASSERT(common->has_set_som);+ if (has_quit && !setsom_found)+ {+ kept_shared_srcw[0] = OVECTOR(0);+ kept_shared_count = 1;+ setsom_found = TRUE;+ }+ cc += 1;+ break;++ case OP_RECURSE:+ if (has_quit)+ {+ if (common->has_set_som && !setsom_found)+ {+ kept_shared_srcw[0] = OVECTOR(0);+ kept_shared_count = 1;+ setsom_found = TRUE;+ }+ if (common->mark_ptr != 0 && !setmark_found)+ {+ kept_shared_srcw[kept_shared_count] = common->mark_ptr;+ kept_shared_count++;+ setmark_found = TRUE;+ }+ }+ if (common->capture_last_ptr != 0 && !capture_last_found)+ {+ shared_srcw[0] = common->capture_last_ptr;+ shared_count = 1;+ capture_last_found = TRUE;+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_KET:+ if (PRIVATE_DATA(cc) != 0)+ {+ private_count = 1;+ private_srcw[0] = PRIVATE_DATA(cc);+ SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);+ cc += PRIVATE_DATA(cc + 1);+ }+ cc += 1 + LINK_SIZE;+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRAPOS:+ case OP_SBRA:+ case OP_SBRAPOS:+ case OP_SCOND:+ private_count = 1;+ private_srcw[0] = PRIVATE_DATA(cc);+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRA:+ case OP_SCBRA:+ offset = (GET2(cc, 1 + LINK_SIZE)) << 1;+ shared_srcw[0] = OVECTOR(offset);+ shared_srcw[1] = OVECTOR(offset + 1);+ shared_count = 2;++ if (common->capture_last_ptr != 0 && !capture_last_found)+ {+ shared_srcw[2] = common->capture_last_ptr;+ shared_count = 3;+ capture_last_found = TRUE;+ }++ if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)+ {+ private_count = 1;+ private_srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));+ }+ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ offset = (GET2(cc, 1 + LINK_SIZE)) << 1;+ shared_srcw[0] = OVECTOR(offset);+ shared_srcw[1] = OVECTOR(offset + 1);+ shared_count = 2;++ if (common->capture_last_ptr != 0 && !capture_last_found)+ {+ shared_srcw[2] = common->capture_last_ptr;+ shared_count = 3;+ capture_last_found = TRUE;+ }++ private_count = 2;+ private_srcw[0] = PRIVATE_DATA(cc);+ private_srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));+ cc += 1 + LINK_SIZE + IMM2_SIZE;+ break;++ case OP_COND:+ /* Might be a hidden SCOND. */+ alternative = cc + GET(cc, 1);+ if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)+ {+ private_count = 1;+ private_srcw[0] = PRIVATE_DATA(cc);+ }+ cc += 1 + LINK_SIZE;+ break;++ CASE_ITERATOR_PRIVATE_DATA_1+ if (PRIVATE_DATA(cc))+ {+ private_count = 1;+ private_srcw[0] = PRIVATE_DATA(cc);+ }+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_PRIVATE_DATA_2A+ if (PRIVATE_DATA(cc))+ {+ private_count = 2;+ private_srcw[0] = PRIVATE_DATA(cc);+ private_srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);+ }+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_PRIVATE_DATA_2B+ if (PRIVATE_DATA(cc))+ {+ private_count = 2;+ private_srcw[0] = PRIVATE_DATA(cc);+ private_srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);+ }+ cc += 2 + IMM2_SIZE;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_1+ if (PRIVATE_DATA(cc))+ {+ private_count = 1;+ private_srcw[0] = PRIVATE_DATA(cc);+ }+ cc += 1;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_2A+ if (PRIVATE_DATA(cc))+ {+ private_count = 2;+ private_srcw[0] = PRIVATE_DATA(cc);+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);+ }+ cc += 1;+ break;++ CASE_ITERATOR_TYPE_PRIVATE_DATA_2B+ if (PRIVATE_DATA(cc))+ {+ private_count = 2;+ private_srcw[0] = PRIVATE_DATA(cc);+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);+ }+ cc += 1 + IMM2_SIZE;+ break;++ case OP_CLASS:+ case OP_NCLASS:+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ i = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR);+#else+ i = 1 + 32 / (int)sizeof(PCRE2_UCHAR);+#endif+ if (PRIVATE_DATA(cc) != 0)+ switch(get_class_iterator_size(cc + i))+ {+ case 1:+ private_count = 1;+ private_srcw[0] = PRIVATE_DATA(cc);+ break;++ case 2:+ private_count = 2;+ private_srcw[0] = PRIVATE_DATA(cc);+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ cc += i;+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_THEN_ARG:+ SLJIT_ASSERT(common->mark_ptr != 0);+ if (has_quit && !setmark_found)+ {+ kept_shared_srcw[0] = common->mark_ptr;+ kept_shared_count = 1;+ setmark_found = TRUE;+ }+ if (common->control_head_ptr != 0 && !control_head_found)+ {+ private_srcw[0] = common->control_head_ptr;+ private_count = 1;+ control_head_found = TRUE;+ }+ cc += 1 + 2 + cc[1];+ break;++ case OP_THEN:+ SLJIT_ASSERT(common->control_head_ptr != 0);+ if (!control_head_found)+ {+ private_srcw[0] = common->control_head_ptr;+ private_count = 1;+ control_head_found = TRUE;+ }+ cc++;+ break;++ default:+ cc = next_opcode(common, cc);+ SLJIT_ASSERT(cc != NULL);+ break;+ }++ if (type != recurse_copy_shared_to_global && type != recurse_copy_kept_shared_to_global)+ {+ SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_private_to_global || type == recurse_swap_global);++ for (i = 0; i < private_count; i++)+ {+ SLJIT_ASSERT(private_srcw[i] != 0);++ if (!from_sp)+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, private_srcw[i]);++ if (from_sp || type == recurse_swap_global)+ delayed_mem_copy_move(&status, SLJIT_SP, private_srcw[i], base_reg, stackptr);++ stackptr += sizeof(sljit_sw);+ }+ }+ else+ stackptr += sizeof(sljit_sw) * private_count;++ if (type != recurse_copy_private_to_global && type != recurse_copy_kept_shared_to_global)+ {+ SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_shared_to_global || type == recurse_swap_global);++ for (i = 0; i < shared_count; i++)+ {+ SLJIT_ASSERT(shared_srcw[i] != 0);++ if (!from_sp)+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, shared_srcw[i]);++ if (from_sp || type == recurse_swap_global)+ delayed_mem_copy_move(&status, SLJIT_SP, shared_srcw[i], base_reg, stackptr);++ stackptr += sizeof(sljit_sw);+ }+ }+ else+ stackptr += sizeof(sljit_sw) * shared_count;++ if (type != recurse_copy_private_to_global && type != recurse_swap_global)+ {+ SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_shared_to_global || type == recurse_copy_kept_shared_to_global);++ for (i = 0; i < kept_shared_count; i++)+ {+ SLJIT_ASSERT(kept_shared_srcw[i] != 0);++ if (!from_sp)+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, kept_shared_srcw[i]);++ if (from_sp || type == recurse_swap_global)+ delayed_mem_copy_move(&status, SLJIT_SP, kept_shared_srcw[i], base_reg, stackptr);++ stackptr += sizeof(sljit_sw);+ }+ }+ else+ stackptr += sizeof(sljit_sw) * kept_shared_count;+ }++SLJIT_ASSERT(cc == ccend && stackptr == stacktop);++delayed_mem_copy_finish(&status);+}++static SLJIT_INLINE PCRE2_SPTR set_then_offsets(compiler_common *common, PCRE2_SPTR cc, sljit_u8 *current_offset)+{+PCRE2_SPTR end = bracketend(cc);+BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT;++/* Assert captures then. */+if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA)+ current_offset = NULL;+/* Conditional block does not. */+if (*cc == OP_COND || *cc == OP_SCOND)+ has_alternatives = FALSE;++cc = next_opcode(common, cc);+if (has_alternatives)+ current_offset = common->then_offsets + (cc - common->start);++while (cc < end)+ {+ if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND))+ cc = set_then_offsets(common, cc, current_offset);+ else+ {+ if (*cc == OP_ALT && has_alternatives)+ current_offset = common->then_offsets + (cc + 1 + LINK_SIZE - common->start);+ if (*cc >= OP_THEN && *cc <= OP_THEN_ARG && current_offset != NULL)+ *current_offset = 1;+ cc = next_opcode(common, cc);+ }+ }++return end;+}++#undef CASE_ITERATOR_PRIVATE_DATA_1+#undef CASE_ITERATOR_PRIVATE_DATA_2A+#undef CASE_ITERATOR_PRIVATE_DATA_2B+#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_1+#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2A+#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2B++static SLJIT_INLINE BOOL is_powerof2(unsigned int value)+{+return (value & (value - 1)) == 0;+}++static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)+{+while (list)+ {+ /* sljit_set_label is clever enough to do nothing+ if either the jump or the label is NULL. */+ SET_LABEL(list->jump, label);+ list = list->next;+ }+}++static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump *jump)+{+jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));+if (list_item)+ {+ list_item->next = *list;+ list_item->jump = jump;+ *list = list_item;+ }+}++static void add_stub(compiler_common *common, struct sljit_jump *start)+{+DEFINE_COMPILER;+stub_list *list_item = sljit_alloc_memory(compiler, sizeof(stub_list));++if (list_item)+ {+ list_item->start = start;+ list_item->quit = LABEL();+ list_item->next = common->stubs;+ common->stubs = list_item;+ }+}++static void flush_stubs(compiler_common *common)+{+DEFINE_COMPILER;+stub_list *list_item = common->stubs;++while (list_item)+ {+ JUMPHERE(list_item->start);+ add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));+ JUMPTO(SLJIT_JUMP, list_item->quit);+ list_item = list_item->next;+ }+common->stubs = NULL;+}++static SLJIT_INLINE void count_match(compiler_common *common)+{+DEFINE_COMPILER;++OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);+add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO));+}++static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)+{+/* May destroy all locals and registers except TMP2. */+DEFINE_COMPILER;++SLJIT_ASSERT(size > 0);+OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));+#ifdef DESTROY_REGISTERS+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);+OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);+OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP1, 0);+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0);+#endif+add_stub(common, CMP(SLJIT_LESS, STACK_TOP, 0, STACK_LIMIT, 0));+}++static SLJIT_INLINE void free_stack(compiler_common *common, int size)+{+DEFINE_COMPILER;++SLJIT_ASSERT(size > 0);+OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));+}++static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size)+{+DEFINE_COMPILER;+sljit_uw *result;++if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;++result = (sljit_uw *)SLJIT_MALLOC(size + sizeof(sljit_uw), compiler->allocator_data);+if (SLJIT_UNLIKELY(result == NULL))+ {+ sljit_set_compiler_memory_error(compiler);+ return NULL;+ }++*(void**)result = common->read_only_data_head;+common->read_only_data_head = (void *)result;+return result + 1;+}++static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)+{+DEFINE_COMPILER;+struct sljit_label *loop;+sljit_s32 i;++/* At this point we can freely use all temporary registers. */+SLJIT_ASSERT(length > 1);+/* TMP1 returns with begin - 1. */+OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1));+if (length < 8)+ {+ for (i = 1; i < length; i++)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), SLJIT_R0, 0);+ }+else+ {+ if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS)+ {+ GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START);+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);+ loop = LABEL();+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw));+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, loop);+ }+ else+ {+ GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START + sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);+ loop = LABEL();+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);+ OP2(SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, loop);+ }+ }+}++static SLJIT_INLINE void reset_early_fail(compiler_common *common)+{+DEFINE_COMPILER;+sljit_u32 size = (sljit_u32)(common->early_fail_end_ptr - common->early_fail_start_ptr);+sljit_u32 uncleared_size;+sljit_s32 src = SLJIT_IMM;+sljit_s32 i;+struct sljit_label *loop;++SLJIT_ASSERT(common->early_fail_start_ptr < common->early_fail_end_ptr);++if (size == sizeof(sljit_sw))+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->early_fail_start_ptr, SLJIT_IMM, 0);+ return;+ }++if (sljit_get_register_index(TMP3) >= 0 && !sljit_has_cpu_feature(SLJIT_HAS_ZERO_REGISTER))+ {+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);+ src = TMP3;+ }++if (size <= 6 * sizeof(sljit_sw))+ {+ for (i = common->early_fail_start_ptr; i < common->early_fail_end_ptr; i += sizeof(sljit_sw))+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), i, src, 0);+ return;+ }++GET_LOCAL_BASE(TMP1, 0, common->early_fail_start_ptr);++uncleared_size = ((size / sizeof(sljit_sw)) % 3) * sizeof(sljit_sw);++OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, size - uncleared_size);++loop = LABEL();+OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), 0, src, 0);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));+OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -2 * (sljit_sw)sizeof(sljit_sw), src, 0);+OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -1 * (sljit_sw)sizeof(sljit_sw), src, 0);+CMPTO(SLJIT_LESS, TMP1, 0, TMP2, 0, loop);++if (uncleared_size >= sizeof(sljit_sw))+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), 0, src, 0);++if (uncleared_size >= 2 * sizeof(sljit_sw))+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), sizeof(sljit_sw), src, 0);+}++static SLJIT_INLINE void do_reset_match(compiler_common *common, int length)+{+DEFINE_COMPILER;+struct sljit_label *loop;+int i;++SLJIT_ASSERT(length > 1);+/* OVECTOR(1) contains the "string begin - 1" constant. */+if (length > 2)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));+if (length < 8)+ {+ for (i = 2; i < length; i++)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), TMP1, 0);+ }+else+ {+ if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS)+ {+ GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw));+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);+ loop = LABEL();+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, loop);+ }+ else+ {+ GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + 2 * sizeof(sljit_sw));+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);+ loop = LABEL();+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(sljit_sw));+ OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, loop);+ }+ }++if (!HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, stack));+else+ OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);++if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);+if (common->control_head_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);+if (HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));++OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, end));+}++static sljit_sw SLJIT_FUNC do_search_mark(sljit_sw *current, PCRE2_SPTR skip_arg)+{+while (current != NULL)+ {+ switch (current[1])+ {+ case type_then_trap:+ break;++ case type_mark:+ if (PRIV(strcmp)(skip_arg, (PCRE2_SPTR)current[2]) == 0)+ return current[3];+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]);+ current = (sljit_sw*)current[0];+ }+return 0;+}++static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)+{+DEFINE_COMPILER;+struct sljit_label *loop;+BOOL has_pre;++/* At this point we can freely use all registers. */+OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0);++if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);+ if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);+ OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, oveccount));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);+ if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);+ OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data),+ SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));+ }+else+ {+ OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, match_data));+ if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);+ OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, oveccount));+ OP1(SLJIT_MOV, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);+ if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R0, 0);+ OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));+ }++has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS;++GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0));+OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? SLJIT_R0 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));++loop = LABEL();++if (has_pre)+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));+else+ {+ OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));+ }++OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, sizeof(PCRE2_SIZE));+OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0);+/* Copy the integer value to the output buffer */+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif++SLJIT_ASSERT(sizeof(PCRE2_SIZE) == 4 || sizeof(PCRE2_SIZE) == 8);+OP1(((sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV), SLJIT_MEM1(SLJIT_R2), 0, SLJIT_S1, 0);++OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+JUMPTO(SLJIT_NOT_ZERO, loop);++/* Calculate the return value, which is the maximum ovector value. */+if (topbracket > 1)+ {+ if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))) == SLJIT_SUCCESS)+ {+ GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);++ /* OVECTOR(0) is never equal to SLJIT_S2. */+ loop = LABEL();+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw)));+ OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);+ }+ else+ {+ GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + (topbracket - 1) * 2 * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);++ /* OVECTOR(0) is never equal to SLJIT_S2. */+ loop = LABEL();+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), 0);+ OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * (sljit_sw)sizeof(sljit_sw));+ OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);+ }+ }+else+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);+}++static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *quit)+{+DEFINE_COMPILER;+sljit_s32 mov_opcode;+sljit_s32 arguments_reg = !HAS_VIRTUAL_REGISTERS ? ARGUMENTS : SLJIT_R1;++SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S0, str_end_must_be_saved_reg0);+SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0+ && (common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start != 0 : common->hit_start == 0));++if (arguments_reg != ARGUMENTS)+ OP1(SLJIT_MOV, arguments_reg, 0, ARGUMENTS, 0);+OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP),+ common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start : common->start_ptr);+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_PARTIAL);++/* Store match begin and end. */+OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, begin));+OP1(SLJIT_MOV, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_R2, 0);+OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, match_data));++mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;++OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S1, 0);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif+OP1(mov_opcode, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(pcre2_match_data, ovector), SLJIT_R2, 0);++OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_S1, 0);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+OP2(SLJIT_ASHR, STR_END, 0, STR_END, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif+OP1(mov_opcode, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(pcre2_match_data, ovector) + sizeof(PCRE2_SIZE), STR_END, 0);++JUMPTO(SLJIT_JUMP, quit);+}++static SLJIT_INLINE void check_start_used_ptr(compiler_common *common)+{+/* May destroy TMP1. */+DEFINE_COMPILER;+struct sljit_jump *jump;++if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ /* The value of -1 must be kept for start_used_ptr! */+ OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, 1);+ /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting+ is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */+ jump = CMP(SLJIT_LESS_EQUAL, TMP1, 0, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+ JUMPHERE(jump);+ }+else if (common->mode == PCRE2_JIT_PARTIAL_HARD)+ {+ jump = CMP(SLJIT_LESS_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+ JUMPHERE(jump);+ }+}++static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, PCRE2_SPTR cc)+{+/* Detects if the character has an othercase. */+unsigned int c;++#ifdef SUPPORT_UNICODE+if (common->utf || common->ucp)+ {+ if (common->utf)+ {+ GETCHAR(c, cc);+ }+ else+ c = *cc;++ if (c > 127)+ return c != UCD_OTHERCASE(c);++ return common->fcc[c] != c;+ }+else+#endif+ c = *cc;+return MAX_255(c) ? common->fcc[c] != c : FALSE;+}++static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)+{+/* Returns with the othercase. */+#ifdef SUPPORT_UNICODE+if ((common->utf || common->ucp) && c > 127)+ return UCD_OTHERCASE(c);+#endif+return TABLE_GET(c, common->fcc, c);+}++static unsigned int char_get_othercase_bit(compiler_common *common, PCRE2_SPTR cc)+{+/* Detects if the character and its othercase has only 1 bit difference. */+unsigned int c, oc, bit;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+int n;+#endif++#ifdef SUPPORT_UNICODE+if (common->utf || common->ucp)+ {+ if (common->utf)+ {+ GETCHAR(c, cc);+ }+ else+ c = *cc;++ if (c <= 127)+ oc = common->fcc[c];+ else+ oc = UCD_OTHERCASE(c);+ }+else+ {+ c = *cc;+ oc = TABLE_GET(c, common->fcc, c);+ }+#else+c = *cc;+oc = TABLE_GET(c, common->fcc, c);+#endif++SLJIT_ASSERT(c != oc);++bit = c ^ oc;+/* Optimized for English alphabet. */+if (c <= 127 && bit == 0x20)+ return (0 << 8) | 0x20;++/* Since c != oc, they must have at least 1 bit difference. */+if (!is_powerof2(bit))+ return 0;++#if PCRE2_CODE_UNIT_WIDTH == 8++#ifdef SUPPORT_UNICODE+if (common->utf && c > 127)+ {+ n = GET_EXTRALEN(*cc);+ while ((bit & 0x3f) == 0)+ {+ n--;+ bit >>= 6;+ }+ return (n << 8) | bit;+ }+#endif /* SUPPORT_UNICODE */+return (0 << 8) | bit;++#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32++#ifdef SUPPORT_UNICODE+if (common->utf && c > 65535)+ {+ if (bit >= (1u << 10))+ bit >>= 10;+ else+ return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8));+ }+#endif /* SUPPORT_UNICODE */+return (bit < 256) ? ((0u << 8) | bit) : ((1u << 8) | (bit >> 8));++#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+}++static void check_partial(compiler_common *common, BOOL force)+{+/* Checks whether a partial matching is occurred. Does not modify registers. */+DEFINE_COMPILER;+struct sljit_jump *jump = NULL;++SLJIT_ASSERT(!force || common->mode != PCRE2_JIT_COMPLETE);++if (common->mode == PCRE2_JIT_COMPLETE)+ return;++if (!force && !common->allow_empty_partial)+ jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ jump = CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);++if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);+else+ {+ if (common->partialmatchlabel != NULL)+ JUMPTO(SLJIT_JUMP, common->partialmatchlabel);+ else+ add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));+ }++if (jump != NULL)+ JUMPHERE(jump);+}++static void check_str_end(compiler_common *common, jump_list **end_reached)+{+/* Does not affect registers. Usually used in a tight spot. */+DEFINE_COMPILER;+struct sljit_jump *jump;++if (common->mode == PCRE2_JIT_COMPLETE)+ {+ add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));+ return;+ }++jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);+ add_jump(compiler, end_reached, JUMP(SLJIT_JUMP));+ }+else+ {+ add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));+ if (common->partialmatchlabel != NULL)+ JUMPTO(SLJIT_JUMP, common->partialmatchlabel);+ else+ add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));+ }+JUMPHERE(jump);+}++static void detect_partial_match(compiler_common *common, jump_list **backtracks)+{+DEFINE_COMPILER;+struct sljit_jump *jump;++if (common->mode == PCRE2_JIT_COMPLETE)+ {+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));+ return;+ }++/* Partial matching mode. */+jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);+if (!common->allow_empty_partial)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));+else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1));++if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ }+else+ {+ if (common->partialmatchlabel != NULL)+ JUMPTO(SLJIT_JUMP, common->partialmatchlabel);+ else+ add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));+ }+JUMPHERE(jump);+}++static void process_partial_match(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_jump *jump;++/* Partial matching mode. */+if (common->mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);+ JUMPHERE(jump);+ }+else if (common->mode == PCRE2_JIT_PARTIAL_HARD)+ {+ if (common->partialmatchlabel != NULL)+ CMPTO(SLJIT_LESS, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0, common->partialmatchlabel);+ else+ add_jump(compiler, &common->partialmatch, CMP(SLJIT_LESS, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));+ }+}++static void detect_partial_match_to(compiler_common *common, struct sljit_label *label)+{+DEFINE_COMPILER;++CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, label);+process_partial_match(common);+}++static void peek_char(compiler_common *common, sljit_u32 max, sljit_s32 dst, sljit_sw dstw, jump_list **backtracks)+{+/* Reads the character into TMP1, keeps STR_PTR.+Does not check STR_END. TMP2, dst, RETURN_ADDR Destroyed. */+DEFINE_COMPILER;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_jump *jump;+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */++SLJIT_UNUSED_ARG(max);+SLJIT_UNUSED_ARG(dst);+SLJIT_UNUSED_ARG(dstw);+SLJIT_UNUSED_ARG(backtracks);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+ if (max < 128) return;++ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);+ OP1(SLJIT_MOV, dst, dstw, STR_PTR, 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ add_jump(compiler, common->invalid_utf ? &common->utfreadchar_invalid : &common->utfreadchar, JUMP(SLJIT_FAST_CALL));+ OP1(SLJIT_MOV, STR_PTR, 0, dst, dstw);+ if (backtracks && common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 16+if (common->utf)+ {+ if (max < 0xd800) return;++ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);++ if (common->invalid_utf)+ {+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);+ OP1(SLJIT_MOV, dst, dstw, STR_PTR, 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));+ OP1(SLJIT_MOV, STR_PTR, 0, dst, dstw);+ if (backtracks && common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ }+ else+ {+ /* TMP2 contains the high surrogate. */+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+ }++ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 32+if (common->invalid_utf)+ {+ if (max < 0xd800) return;++ if (backtracks != NULL)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));+ }+ else+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);+ }+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+#endif /* SUPPORT_UNICODE */+}++static void peek_char_back(compiler_common *common, sljit_u32 max, jump_list **backtracks)+{+/* Reads one character back without moving STR_PTR. TMP2 must+contain the start of the subject buffer. Affects TMP1, TMP2, and RETURN_ADDR. */+DEFINE_COMPILER;++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_jump *jump;+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */++SLJIT_UNUSED_ARG(max);+SLJIT_UNUSED_ARG(backtracks);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+ if (max < 128) return;++ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);+ if (common->invalid_utf)+ {+ add_jump(compiler, &common->utfpeakcharback_invalid, JUMP(SLJIT_FAST_CALL));+ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ }+ else+ add_jump(compiler, &common->utfpeakcharback, JUMP(SLJIT_FAST_CALL));+ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 16+if (common->utf)+ {+ if (max < 0xd800) return;++ if (common->invalid_utf)+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);+ add_jump(compiler, &common->utfpeakcharback_invalid, JUMP(SLJIT_FAST_CALL));+ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ }+ else+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xdc00);+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xdc00);+ /* TMP2 contains the low surrogate. */+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x10000);+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+ }+ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 32+if (common->invalid_utf)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+#endif /* SUPPORT_UNICODE */+}++#define READ_CHAR_UPDATE_STR_PTR 0x1+#define READ_CHAR_UTF8_NEWLINE 0x2+#define READ_CHAR_NEWLINE (READ_CHAR_UPDATE_STR_PTR | READ_CHAR_UTF8_NEWLINE)+#define READ_CHAR_VALID_UTF 0x4++static void read_char(compiler_common *common, sljit_u32 min, sljit_u32 max,+ jump_list **backtracks, sljit_u32 options)+{+/* Reads the precise value of a character into TMP1, if the character is+between min and max (c >= min && c <= max). Otherwise it returns with a value+outside the range. Does not check STR_END. */+DEFINE_COMPILER;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_jump *jump;+#endif+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+struct sljit_jump *jump2;+#endif++SLJIT_UNUSED_ARG(min);+SLJIT_UNUSED_ARG(max);+SLJIT_UNUSED_ARG(backtracks);+SLJIT_UNUSED_ARG(options);+SLJIT_ASSERT(min <= max);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+ if (max < 128 && !(options & READ_CHAR_UPDATE_STR_PTR)) return;++ if (common->invalid_utf && !(options & READ_CHAR_VALID_UTF))+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);++ if (options & READ_CHAR_UTF8_NEWLINE)+ add_jump(compiler, &common->utfreadnewline_invalid, JUMP(SLJIT_FAST_CALL));+ else+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));++ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ JUMPHERE(jump);+ return;+ }++ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);+ if (min >= 0x10000)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x7);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));+ if (!(options & READ_CHAR_UPDATE_STR_PTR))+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+ JUMPHERE(jump2);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);+ }+ else if (min >= 0x800 && max <= 0xffff)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xe0);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xf);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ if (!(options & READ_CHAR_UPDATE_STR_PTR))+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+ JUMPHERE(jump2);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);+ }+ else if (max >= 0x800)+ {+ add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));+ }+ else if (max < 128)+ {+ OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+ }+ else+ {+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ if (!(options & READ_CHAR_UPDATE_STR_PTR))+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ else+ OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);+ }+ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 16+if (common->utf)+ {+ if (max < 0xd800 && !(options & READ_CHAR_UPDATE_STR_PTR)) return;++ if (common->invalid_utf && !(options & READ_CHAR_VALID_UTF))+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);++ if (options & READ_CHAR_UTF8_NEWLINE)+ add_jump(compiler, &common->utfreadnewline_invalid, JUMP(SLJIT_FAST_CALL));+ else+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));++ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ JUMPHERE(jump);+ return;+ }++ if (max >= 0x10000)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800);+ /* TMP2 contains the high surrogate. */+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+ JUMPHERE(jump);+ return;+ }++ /* Skip low surrogate if necessary. */+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)+ {+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x400);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ CMOV(SLJIT_LESS, STR_PTR, RETURN_ADDR, 0);+ if (max >= 0xd800)+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, 0x10000);+ }+ else+ {+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);+ if (options & READ_CHAR_UPDATE_STR_PTR)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ if (max >= 0xd800)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);+ JUMPHERE(jump);+ }+ }+#elif PCRE2_CODE_UNIT_WIDTH == 32+if (common->invalid_utf)+ {+ if (backtracks != NULL)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));+ }+ else+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);+ }+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+#endif /* SUPPORT_UNICODE */+}++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8++static BOOL is_char7_bitset(const sljit_u8 *bitset, BOOL nclass)+{+/* Tells whether the character codes below 128 are enough+to determine a match. */+const sljit_u8 value = nclass ? 0xff : 0;+const sljit_u8 *end = bitset + 32;++bitset += 16;+do+ {+ if (*bitset++ != value)+ return FALSE;+ }+while (bitset < end);+return TRUE;+}++static void read_char7_type(compiler_common *common, jump_list **backtracks, BOOL negated)+{+/* Reads the precise character type of a character into TMP1, if the character+is less than 128. Otherwise it returns with zero. Does not check STR_END. The+full_read argument tells whether characters above max are accepted or not. */+DEFINE_COMPILER;+struct sljit_jump *jump;++SLJIT_ASSERT(common->utf);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++/* All values > 127 are zero in ctypes. */+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);++if (negated)+ {+ jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x80);++ if (common->invalid_utf)+ {+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+ }+ else+ {+ OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+ }+ JUMPHERE(jump);+ }+}++#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */++static void read_char8_type(compiler_common *common, jump_list **backtracks, BOOL negated)+{+/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */+DEFINE_COMPILER;+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+struct sljit_jump *jump;+#endif+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+struct sljit_jump *jump2;+#endif++SLJIT_UNUSED_ARG(backtracks);+SLJIT_UNUSED_ARG(negated);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+ /* The result of this read may be unused, but saves an "else" part. */+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);+ jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x80);++ if (!negated)+ {+ if (common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);+ if (common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe0 - 0xc2));++ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);+ if (common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40));++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+ jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);+ JUMPHERE(jump2);+ }+ else if (common->invalid_utf)+ {+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));+ OP1(SLJIT_MOV, TMP2, 0, TMP1, 0);+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+ jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);+ JUMPHERE(jump2);+ }+ else+ add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));++ JUMPHERE(jump);+ return;+ }+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 32+if (common->invalid_utf && negated)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x110000));+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 32 */++#if PCRE2_CODE_UNIT_WIDTH != 8+/* The ctypes array contains only 256 values. */+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);+#if PCRE2_CODE_UNIT_WIDTH != 8+JUMPHERE(jump);+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16+if (common->utf && negated)+ {+ /* Skip low surrogate if necessary. */+ if (!common->invalid_utf)+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)+ {+ OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x400);+ CMOV(SLJIT_LESS, STR_PTR, RETURN_ADDR, 0);+ }+ else+ {+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPHERE(jump);+ }+ return;+ }++ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400));+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xdc00);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400));++ JUMPHERE(jump);+ return;+ }+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16 */+}++static void move_back(compiler_common *common, jump_list **backtracks, BOOL must_be_valid)+{+/* Goes one character back. Affects STR_PTR and TMP1. If must_be_valid is TRUE,+TMP2 is not used. Otherwise TMP2 must contain the start of the subject buffer,+and it is destroyed. Does not modify STR_PTR for invalid character sequences. */+DEFINE_COMPILER;++SLJIT_UNUSED_ARG(backtracks);+SLJIT_UNUSED_ARG(must_be_valid);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_jump *jump;+#endif++#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+struct sljit_label *label;++if (common->utf)+ {+ if (!must_be_valid && common->invalid_utf)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);+ add_jump(compiler, &common->utfmoveback_invalid, JUMP(SLJIT_FAST_CALL));+ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));+ JUMPHERE(jump);+ return;+ }++ label = LABEL();+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);+ CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);+ return;+ }+#elif PCRE2_CODE_UNIT_WIDTH == 16+if (common->utf)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ if (!must_be_valid && common->invalid_utf)+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000 - 0xd800);+ add_jump(compiler, &common->utfmoveback_invalid, JUMP(SLJIT_FAST_CALL));+ if (backtracks != NULL)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));+ JUMPHERE(jump);+ return;+ }++ /* Skip low surrogate if necessary. */+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ return;+ }+#elif PCRE2_CODE_UNIT_WIDTH == 32+if (common->invalid_utf && !must_be_valid)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));+ if (backtracks != NULL)+ {+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ return;+ }++ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_LESS);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ return;+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+#endif /* SUPPORT_UNICODE */+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+}++static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpifmatch)+{+/* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */+DEFINE_COMPILER;+struct sljit_jump *jump;++if (nltype == NLTYPE_ANY)+ {+ add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));+ sljit_set_current_flags(compiler, SLJIT_SET_Z);+ add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_NOT_ZERO : SLJIT_ZERO));+ }+else if (nltype == NLTYPE_ANYCRLF)+ {+ if (jumpifmatch)+ {+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR));+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));+ }+ else+ {+ jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));+ JUMPHERE(jump);+ }+ }+else+ {+ SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);+ add_jump(compiler, backtracks, CMP(jumpifmatch ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));+ }+}++#ifdef SUPPORT_UNICODE++#if PCRE2_CODE_UNIT_WIDTH == 8+static void do_utfreadchar(compiler_common *common)+{+/* Fast decoding a UTF-8 character. TMP1 contains the first byte+of the character (>= 0xc0). Return char value in TMP1. */+DEFINE_COMPILER;+struct sljit_jump *jump;++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++/* Searching for the first zero. */+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);+jump = JUMP(SLJIT_NOT_ZERO);+/* Two byte sequence. */+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3000);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);+jump = JUMP(SLJIT_NOT_ZERO);+/* Three byte sequence. */+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0000);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Four byte sequence. */+JUMPHERE(jump);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xf0000);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfreadtype8(compiler_common *common)+{+/* Fast decoding a UTF-8 character type. TMP2 contains the first byte+of the character (>= 0xc0). Return value in TMP1. */+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_jump *compare;++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);+jump = JUMP(SLJIT_NOT_ZERO);+/* Two byte sequence. */+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);+/* The upper 5 bits are known at this point. */+compare = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x3);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);+OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(compare);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* We only have types for characters less than 256. */+JUMPHERE(jump);+OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfreadchar_invalid(compiler_common *common)+{+/* Slow decoding a UTF-8 character. TMP1 contains the first byte+of the character (>= 0xc0). Return char value in TMP1. STR_PTR is+undefined for invalid characters. */+DEFINE_COMPILER;+sljit_s32 i;+sljit_s32 has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV);+struct sljit_jump *jump;+struct sljit_jump *buffer_end_close;+struct sljit_label *three_byte_entry;+struct sljit_label *exit_invalid_label;+struct sljit_jump *exit_invalid[11];++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc2);++/* Usually more than 3 characters remained in the subject buffer. */+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));++/* Not a valid start of a multi-byte sequence, no more bytes read. */+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xf5 - 0xc2);++buffer_end_close = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+/* If TMP2 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);++OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);+jump = JUMP(SLJIT_NOT_ZERO);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump);++/* Three-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+if (has_cmov)+ {+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x40);+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, 0x20000);+ exit_invalid[2] = NULL;+ }+else+ exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);++OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);+jump = JUMP(SLJIT_NOT_ZERO);++three_byte_entry = LABEL();++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2d800);+if (has_cmov)+ {+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0xd800);+ exit_invalid[3] = NULL;+ }+else+ exit_invalid[3] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (has_cmov)+ {+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);+ exit_invalid[4] = NULL;+ }+else+ exit_invalid[4] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump);++/* Four-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+if (has_cmov)+ {+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x40);+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, 0);+ exit_invalid[5] = NULL;+ }+else+ exit_invalid[5] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc10000);+if (has_cmov)+ {+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x100000);+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0x10000);+ exit_invalid[6] = NULL;+ }+else+ exit_invalid[6] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(buffer_end_close);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+exit_invalid[7] = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);++/* Two-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+/* If TMP2 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+exit_invalid[8] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);++OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);+jump = JUMP(SLJIT_NOT_ZERO);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Three-byte sequence. */+JUMPHERE(jump);+exit_invalid[9] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+if (has_cmov)+ {+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x40);+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);+ exit_invalid[10] = NULL;+ }+else+ exit_invalid[10] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);++/* One will be substracted from STR_PTR later. */+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));++/* Four byte sequences are not possible. */+CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x30000, three_byte_entry);++exit_invalid_label = LABEL();+for (i = 0; i < 11; i++)+ sljit_set_label(exit_invalid[i], exit_invalid_label);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfreadnewline_invalid(compiler_common *common)+{+/* Slow decoding a UTF-8 character, specialized for newlines.+TMP1 contains the first byte of the character (>= 0xc0). Return+char value in TMP1. */+DEFINE_COMPILER;+struct sljit_label *loop;+struct sljit_label *skip_start;+struct sljit_label *three_byte_exit;+struct sljit_jump *jump[5];++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++if (common->nltype != NLTYPE_ANY)+ {+ SLJIT_ASSERT(common->nltype != NLTYPE_FIXED || common->newline < 128);++ /* All newlines are ascii, just skip intermediate octets. */+ jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ loop = LABEL();+ if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)) == SLJIT_SUCCESS)+ sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ else+ {+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ }++ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);+ CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ JUMPHERE(jump[0]);++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+ OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+ return;+ }++jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++jump[1] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xc2);+jump[2] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xe2);++skip_start = LABEL();+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);+jump[3] = CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80);++/* Skip intermediate octets. */+loop = LABEL();+jump[4] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);+CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop);++JUMPHERE(jump[3]);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++three_byte_exit = LABEL();+JUMPHERE(jump[0]);+JUMPHERE(jump[4]);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Two byte long newline: 0x85. */+JUMPHERE(jump[1]);+CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x85, skip_start);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x85);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Three byte long newlines: 0x2028 and 0x2029. */+JUMPHERE(jump[2]);+CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, skip_start);+CMPTO(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0, three_byte_exit);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++OP2(SLJIT_SUB, TMP1, 0, TMP2, 0, SLJIT_IMM, 0x80);+CMPTO(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x40, skip_start);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0x2000);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfmoveback_invalid(compiler_common *common)+{+/* Goes one character back. */+DEFINE_COMPILER;+sljit_s32 i;+struct sljit_jump *jump;+struct sljit_jump *buffer_start_close;+struct sljit_label *exit_ok_label;+struct sljit_label *exit_invalid_label;+struct sljit_jump *exit_invalid[7];++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xc0);++/* Two-byte sequence. */+buffer_start_close = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);+jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x20);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Three-byte sequence. */+JUMPHERE(jump);+exit_invalid[1] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, -0x40);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);+jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x10);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Four-byte sequence. */+JUMPHERE(jump);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0 - 0x80);+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x40);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xf0);+exit_invalid[3] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x05);++exit_ok_label = LABEL();+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++/* Two-byte sequence. */+JUMPHERE(buffer_start_close);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));++exit_invalid[4] = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);+CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x20, exit_ok_label);++/* Three-byte sequence. */+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+exit_invalid[5] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, -0x40);+exit_invalid[6] = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);+CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10, exit_ok_label);++/* Four-byte sequences are not possible. */++exit_invalid_label = LABEL();+sljit_set_label(exit_invalid[5], exit_invalid_label);+sljit_set_label(exit_invalid[6], exit_invalid_label);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(exit_invalid[4]);+/* -2 + 4 = 2 */+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));++exit_invalid_label = LABEL();+for (i = 0; i < 4; i++)+ sljit_set_label(exit_invalid[i], exit_invalid_label);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(4));+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfpeakcharback(compiler_common *common)+{+/* Peak a character back. Does not modify STR_PTR. */+DEFINE_COMPILER;+struct sljit_jump *jump[2];++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);+jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x20);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);+jump[1] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-4));+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0 - 0x80);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf0);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++JUMPHERE(jump[1]);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++JUMPHERE(jump[0]);+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfpeakcharback_invalid(compiler_common *common)+{+/* Peak a character back. Does not modify STR_PTR. */+DEFINE_COMPILER;+sljit_s32 i;+sljit_s32 has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV);+struct sljit_jump *jump[2];+struct sljit_label *two_byte_entry;+struct sljit_label *three_byte_entry;+struct sljit_label *exit_invalid_label;+struct sljit_jump *exit_invalid[8];++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xc0);+jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);++/* Two-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);+jump[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x1e);++two_byte_entry = LABEL();+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+/* If TMP1 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump[1]);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2 - 0x80);+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++/* Three-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0);+jump[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x10);++three_byte_entry = LABEL();+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+if (has_cmov)+ {+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, -0xd800);+ exit_invalid[2] = NULL;+ }+else+ exit_invalid[2] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+if (has_cmov)+ {+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);+ exit_invalid[3] = NULL;+ }+else+ exit_invalid[3] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump[1]);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0 - 0x80);+exit_invalid[4] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++/* Four-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-4));+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf0);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 18);+/* ADD is used instead of OR because of the SUB 0x10000 above. */+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);++if (has_cmov)+ {+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x100000);+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0x10000);+ exit_invalid[5] = NULL;+ }+else+ exit_invalid[5] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump[0]);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);++/* Two-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);+CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x1e, two_byte_entry);++OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2 - 0x80);+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);+exit_invalid[6] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);++/* Three-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0);+CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x10, three_byte_entry);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump[0]);+exit_invalid[7] = CMP(SLJIT_GREATER, TMP2, 0, STR_PTR, 0);++/* Two-byte sequence. */+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);+CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x1e, two_byte_entry);++exit_invalid_label = LABEL();+for (i = 0; i < 8; i++)+ sljit_set_label(exit_invalid[i], exit_invalid_label);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */++#if PCRE2_CODE_UNIT_WIDTH == 16++static void do_utfreadchar_invalid(compiler_common *common)+{+/* Slow decoding a UTF-16 character. TMP1 contains the first half+of the character (>= 0xd800). Return char value in TMP1. STR_PTR is+undefined for invalid characters. */+DEFINE_COMPILER;+struct sljit_jump *exit_invalid[3];++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++/* TMP2 contains the high surrogate. */+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00);+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xdc00);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x10000);+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x400);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(exit_invalid[0]);+JUMPHERE(exit_invalid[1]);+JUMPHERE(exit_invalid[2]);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfreadnewline_invalid(compiler_common *common)+{+/* Slow decoding a UTF-16 character, specialized for newlines.+TMP1 contains the first half of the character (>= 0xd800). Return+char value in TMP1. */++DEFINE_COMPILER;+struct sljit_jump *exit_invalid[2];++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++/* TMP2 contains the high surrogate. */+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00);++OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xdc00);+OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x400);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(exit_invalid[0]);+JUMPHERE(exit_invalid[1]);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfmoveback_invalid(compiler_common *common)+{+/* Goes one character back. */+DEFINE_COMPILER;+struct sljit_jump *exit_invalid[3];++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++exit_invalid[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x400);+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x400);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(exit_invalid[0]);+JUMPHERE(exit_invalid[1]);+JUMPHERE(exit_invalid[2]);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_utfpeakcharback_invalid(compiler_common *common)+{+/* Peak a character back. Does not modify STR_PTR. */+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_jump *exit_invalid[3];++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+exit_invalid[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);++OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);++JUMPHERE(jump);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(exit_invalid[0]);+JUMPHERE(exit_invalid[1]);+JUMPHERE(exit_invalid[2]);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */++/* UCD_BLOCK_SIZE must be 128 (see the assert below). */+#define UCD_BLOCK_MASK 127+#define UCD_BLOCK_SHIFT 7++static void do_getucd(compiler_common *common)+{+/* Search the UCD record for the character comes in TMP1.+Returns chartype in TMP1 and UCD offset in TMP2. */+DEFINE_COMPILER;+#if PCRE2_CODE_UNIT_WIDTH == 32+struct sljit_jump *jump;+#endif++#if defined SLJIT_DEBUG && SLJIT_DEBUG+/* dummy_ucd_record */+const ucd_record *record = GET_UCD(UNASSIGNED_UTF_CHAR);+SLJIT_ASSERT(record->script == ucp_Unknown && record->chartype == ucp_Cn && record->gbprop == ucp_gbOther);+SLJIT_ASSERT(record->caseset == 0 && record->other_case == 0);+#endif++SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 12);++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++#if PCRE2_CODE_UNIT_WIDTH == 32+if (!common->utf)+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);+ JUMPHERE(jump);+ }+#endif++OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);+OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));+OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));+OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_getucdtype(compiler_common *common)+{+/* Search the UCD record for the character comes in TMP1.+Returns chartype in TMP1 and UCD offset in TMP2. */+DEFINE_COMPILER;+#if PCRE2_CODE_UNIT_WIDTH == 32+struct sljit_jump *jump;+#endif++#if defined SLJIT_DEBUG && SLJIT_DEBUG+/* dummy_ucd_record */+const ucd_record *record = GET_UCD(UNASSIGNED_UTF_CHAR);+SLJIT_ASSERT(record->script == ucp_Unknown && record->chartype == ucp_Cn && record->gbprop == ucp_gbOther);+SLJIT_ASSERT(record->caseset == 0 && record->other_case == 0);+#endif++SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 12);++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++#if PCRE2_CODE_UNIT_WIDTH == 32+if (!common->utf)+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);+ JUMPHERE(jump);+ }+#endif++OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);+OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));+OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));+OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);++/* TMP2 is multiplied by 12. Same as (TMP2 << 2) + ((TMP2 << 2) << 1). */+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 1);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++#endif /* SUPPORT_UNICODE */++static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_label *mainloop;+struct sljit_label *newlinelabel = NULL;+struct sljit_jump *start;+struct sljit_jump *end = NULL;+struct sljit_jump *end2 = NULL;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_label *loop;+struct sljit_jump *jump;+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */+jump_list *newline = NULL;+sljit_u32 overall_options = common->re->overall_options;+BOOL hascrorlf = (common->re->flags & PCRE2_HASCRORLF) != 0;+BOOL newlinecheck = FALSE;+BOOL readuchar = FALSE;++if (!(hascrorlf || (overall_options & PCRE2_FIRSTLINE) != 0)+ && (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255))+ newlinecheck = TRUE;++SLJIT_ASSERT(common->abort_label == NULL);++if ((overall_options & PCRE2_FIRSTLINE) != 0)+ {+ /* Search for the end of the first line. */+ SLJIT_ASSERT(common->match_end_ptr != 0);+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);++ if (common->nltype == NLTYPE_FIXED && common->newline > 255)+ {+ mainloop = LABEL();+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);+ CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);+ JUMPHERE(end);+ OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ }+ else+ {+ end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ mainloop = LABEL();+ /* Continual stores does not cause data dependency. */+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0);+ read_char(common, common->nlmin, common->nlmax, NULL, READ_CHAR_NEWLINE);+ check_newlinechar(common, common->nltype, &newline, TRUE);+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, mainloop);+ JUMPHERE(end);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0);+ set_jumps(newline, LABEL());+ }++ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+ }+else if ((overall_options & PCRE2_USE_OFFSET_LIMIT) != 0)+ {+ /* Check whether offset limit is set and valid. */+ SLJIT_ASSERT(common->match_end_ptr != 0);++ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, offset_limit));+ }+ else+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, offset_limit));++ OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);+ end = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw) PCRE2_UNSET);+ if (HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);+ else+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));++#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif /* PCRE2_CODE_UNIT_WIDTH == [16|32] */+ if (HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));++ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);+ end2 = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0);+ OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);+ JUMPHERE(end2);+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);+ add_jump(compiler, &common->abort, CMP(SLJIT_LESS, TMP2, 0, STR_PTR, 0));+ JUMPHERE(end);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, TMP2, 0);+ }++start = JUMP(SLJIT_JUMP);++if (newlinecheck)+ {+ newlinelabel = LABEL();+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif /* PCRE2_CODE_UNIT_WIDTH == [16|32] */+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ end2 = JUMP(SLJIT_JUMP);+ }++mainloop = LABEL();++/* Increasing the STR_PTR here requires one less jump in the most common case. */+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && !common->invalid_utf) readuchar = TRUE;+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */+if (newlinecheck) readuchar = TRUE;++if (readuchar)+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);++if (newlinecheck)+ CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->invalid_utf)+ {+ /* Skip continuation code units. */+ loop = LABEL();+ jump = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);+ CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x40, loop);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPHERE(jump);+ }+else if (common->utf)+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ JUMPHERE(jump);+ }+#elif PCRE2_CODE_UNIT_WIDTH == 16+if (common->invalid_utf)+ {+ /* Skip continuation code units. */+ loop = LABEL();+ jump = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xdc00);+ CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x400, loop);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPHERE(jump);+ }+else if (common->utf)+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV))+ {+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);+ CMOV(SLJIT_LESS, STR_PTR, TMP2, 0);+ }+ else+ {+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_LESS);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ }+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */+JUMPHERE(start);++if (newlinecheck)+ {+ JUMPHERE(end);+ JUMPHERE(end2);+ }++return mainloop;+}+++static SLJIT_INLINE void add_prefix_char(PCRE2_UCHAR chr, fast_forward_char_data *chars, BOOL last)+{+sljit_u32 i, count = chars->count;++if (count == 255)+ return;++if (count == 0)+ {+ chars->count = 1;+ chars->chars[0] = chr;++ if (last)+ chars->last_count = 1;+ return;+ }++for (i = 0; i < count; i++)+ if (chars->chars[i] == chr)+ return;++if (count >= MAX_DIFF_CHARS)+ {+ chars->count = 255;+ return;+ }++chars->chars[count] = chr;+chars->count = count + 1;++if (last)+ chars->last_count++;+}++static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, fast_forward_char_data *chars, int max_chars, sljit_u32 *rec_count)+{+/* Recursive function, which scans prefix literals. */+BOOL last, any, class, caseless;+int len, repeat, len_save, consumed = 0;+sljit_u32 chr; /* Any unicode character. */+sljit_u8 *bytes, *bytes_end, byte;+PCRE2_SPTR alternative, cc_save, oc;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+PCRE2_UCHAR othercase[4];+#elif defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16+PCRE2_UCHAR othercase[2];+#else+PCRE2_UCHAR othercase[1];+#endif++repeat = 1;+while (TRUE)+ {+ if (*rec_count == 0)+ return 0;+ (*rec_count)--;++ last = TRUE;+ any = FALSE;+ class = FALSE;+ caseless = FALSE;++ switch (*cc)+ {+ case OP_CHARI:+ caseless = TRUE;+ /* Fall through */+ case OP_CHAR:+ last = FALSE;+ cc++;+ break;++ case OP_SOD:+ case OP_SOM:+ case OP_SET_SOM:+ case OP_NOT_WORD_BOUNDARY:+ case OP_WORD_BOUNDARY:+ case OP_EODN:+ case OP_EOD:+ case OP_CIRC:+ case OP_CIRCM:+ case OP_DOLL:+ case OP_DOLLM:+ /* Zero width assertions. */+ cc++;+ continue;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ cc = bracketend(cc);+ continue;++ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_POSPLUSI:+ caseless = TRUE;+ /* Fall through */+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_POSPLUS:+ cc++;+ break;++ case OP_EXACTI:+ caseless = TRUE;+ /* Fall through */+ case OP_EXACT:+ repeat = GET2(cc, 1);+ last = FALSE;+ cc += 1 + IMM2_SIZE;+ break;++ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_POSQUERYI:+ caseless = TRUE;+ /* Fall through */+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_POSQUERY:+ len = 1;+ cc++;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);+#endif+ max_chars = scan_prefix(common, cc + len, chars, max_chars, rec_count);+ if (max_chars == 0)+ return consumed;+ last = FALSE;+ break;++ case OP_KET:+ cc += 1 + LINK_SIZE;+ continue;++ case OP_ALT:+ cc += GET(cc, 1);+ continue;++ case OP_ONCE:+ case OP_BRA:+ case OP_BRAPOS:+ case OP_CBRA:+ case OP_CBRAPOS:+ alternative = cc + GET(cc, 1);+ while (*alternative == OP_ALT)+ {+ max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, max_chars, rec_count);+ if (max_chars == 0)+ return consumed;+ alternative += GET(alternative, 1);+ }++ if (*cc == OP_CBRA || *cc == OP_CBRAPOS)+ cc += IMM2_SIZE;+ cc += 1 + LINK_SIZE;+ continue;++ case OP_CLASS:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && !is_char7_bitset((const sljit_u8 *)(cc + 1), FALSE))+ return consumed;+#endif+ class = TRUE;+ break;++ case OP_NCLASS:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf) return consumed;+#endif+ class = TRUE;+ break;++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf) return consumed;+#endif+ any = TRUE;+ cc += GET(cc, 1);+ break;+#endif++ case OP_DIGIT:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE))+ return consumed;+#endif+ any = TRUE;+ cc++;+ break;++ case OP_WHITESPACE:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE))+ return consumed;+#endif+ any = TRUE;+ cc++;+ break;++ case OP_WORDCHAR:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE))+ return consumed;+#endif+ any = TRUE;+ cc++;+ break;++ case OP_NOT:+ case OP_NOTI:+ cc++;+ /* Fall through. */+ case OP_NOT_DIGIT:+ case OP_NOT_WHITESPACE:+ case OP_NOT_WORDCHAR:+ case OP_ANY:+ case OP_ALLANY:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf) return consumed;+#endif+ any = TRUE;+ cc++;+ break;++#ifdef SUPPORT_UNICODE+ case OP_NOTPROP:+ case OP_PROP:+#if PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf) return consumed;+#endif+ any = TRUE;+ cc += 1 + 2;+ break;+#endif++ case OP_TYPEEXACT:+ repeat = GET2(cc, 1);+ cc += 1 + IMM2_SIZE;+ continue;++ case OP_NOTEXACT:+ case OP_NOTEXACTI:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf) return consumed;+#endif+ any = TRUE;+ repeat = GET2(cc, 1);+ cc += 1 + IMM2_SIZE + 1;+ break;++ default:+ return consumed;+ }++ if (any)+ {+ do+ {+ chars->count = 255;++ consumed++;+ if (--max_chars == 0)+ return consumed;+ chars++;+ }+ while (--repeat > 0);++ repeat = 1;+ continue;+ }++ if (class)+ {+ bytes = (sljit_u8*) (cc + 1);+ cc += 1 + 32 / sizeof(PCRE2_UCHAR);++ switch (*cc)+ {+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRPOSSTAR:+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSQUERY:+ max_chars = scan_prefix(common, cc + 1, chars, max_chars, rec_count);+ if (max_chars == 0)+ return consumed;+ break;++ default:+ case OP_CRPLUS:+ case OP_CRMINPLUS:+ case OP_CRPOSPLUS:+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ repeat = GET2(cc, 1);+ if (repeat <= 0)+ return consumed;+ break;+ }++ do+ {+ if (bytes[31] & 0x80)+ chars->count = 255;+ else if (chars->count != 255)+ {+ bytes_end = bytes + 32;+ chr = 0;+ do+ {+ byte = *bytes++;+ SLJIT_ASSERT((chr & 0x7) == 0);+ if (byte == 0)+ chr += 8;+ else+ {+ do+ {+ if ((byte & 0x1) != 0)+ add_prefix_char(chr, chars, TRUE);+ byte >>= 1;+ chr++;+ }+ while (byte != 0);+ chr = (chr + 7) & ~7;+ }+ }+ while (chars->count != 255 && bytes < bytes_end);+ bytes = bytes_end - 32;+ }++ consumed++;+ if (--max_chars == 0)+ return consumed;+ chars++;+ }+ while (--repeat > 0);++ switch (*cc)+ {+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRPOSSTAR:+ return consumed;++ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSQUERY:+ cc++;+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ if (GET2(cc, 1) != GET2(cc, 1 + IMM2_SIZE))+ return consumed;+ cc += 1 + 2 * IMM2_SIZE;+ break;+ }++ repeat = 1;+ continue;+ }++ len = 1;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);+#endif++ if (caseless && char_has_othercase(common, cc))+ {+#ifdef SUPPORT_UNICODE+ if (common->utf)+ {+ GETCHAR(chr, cc);+ if ((int)PRIV(ord2utf)(char_othercase(common, chr), othercase) != len)+ return consumed;+ }+ else+#endif+ {+ chr = *cc;+#ifdef SUPPORT_UNICODE+ if (common->ucp && chr > 127)+ othercase[0] = UCD_OTHERCASE(chr);+ else+#endif+ othercase[0] = TABLE_GET(chr, common->fcc, chr);+ }+ }+ else+ {+ caseless = FALSE;+ othercase[0] = 0; /* Stops compiler warning - PH */+ }++ len_save = len;+ cc_save = cc;+ while (TRUE)+ {+ oc = othercase;+ do+ {+ len--;+ consumed++;++ chr = *cc;+ add_prefix_char(*cc, chars, len == 0);++ if (caseless)+ add_prefix_char(*oc, chars, len == 0);++ if (--max_chars == 0)+ return consumed;+ chars++;+ cc++;+ oc++;+ }+ while (len > 0);++ if (--repeat == 0)+ break;++ len = len_save;+ cc = cc_save;+ }++ repeat = 1;+ if (last)+ return consumed;+ }+}++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+static void jumpto_if_not_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg, struct sljit_label *label)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);+CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0x80, label);+#elif PCRE2_CODE_UNIT_WIDTH == 16+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);+CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00, label);+#else+#error "Unknown code width"+#endif+}+#endif++#include "pcre2_jit_simd_inc.h"++#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD++static BOOL check_fast_forward_char_pair_simd(compiler_common *common, fast_forward_char_data *chars, int max)+{+ sljit_s32 i, j, max_i = 0, max_j = 0;+ sljit_u32 max_pri = 0;+ PCRE2_UCHAR a1, a2, a_pri, b1, b2, b_pri;++ for (i = max - 1; i >= 1; i--)+ {+ if (chars[i].last_count > 2)+ {+ a1 = chars[i].chars[0];+ a2 = chars[i].chars[1];+ a_pri = chars[i].last_count;++ j = i - max_fast_forward_char_pair_offset();+ if (j < 0)+ j = 0;++ while (j < i)+ {+ b_pri = chars[j].last_count;+ if (b_pri > 2 && a_pri + b_pri >= max_pri)+ {+ b1 = chars[j].chars[0];+ b2 = chars[j].chars[1];++ if (a1 != b1 && a1 != b2 && a2 != b1 && a2 != b2)+ {+ max_pri = a_pri + b_pri;+ max_i = i;+ max_j = j;+ }+ }+ j++;+ }+ }+ }++if (max_pri == 0)+ return FALSE;++fast_forward_char_pair_simd(common, max_i, chars[max_i].chars[0], chars[max_i].chars[1], max_j, chars[max_j].chars[0], chars[max_j].chars[1]);+return TRUE;+}++#endif /* JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD */++static void fast_forward_first_char2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)+{+DEFINE_COMPILER;+struct sljit_label *start;+struct sljit_jump *match;+struct sljit_jump *partial_quit;+PCRE2_UCHAR mask;+BOOL has_match_end = (common->match_end_ptr != 0);++SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE || offset == 0);++if (has_match_end)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);++if (offset > 0)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));++if (has_match_end)+ {+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);++ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offset + 1));+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0);+ CMOV(SLJIT_GREATER, STR_END, TMP1, 0);+ }++#ifdef JIT_HAS_FAST_FORWARD_CHAR_SIMD++if (JIT_HAS_FAST_FORWARD_CHAR_SIMD)+ {+ fast_forward_char_simd(common, char1, char2, offset);++ if (offset > 0)+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));++ if (has_match_end)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+ return;+ }++#endif++start = LABEL();++partial_quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (char1 == char2)+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char1, start);+else+ {+ mask = char1 ^ char2;+ if (is_powerof2(mask))+ {+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask, start);+ }+ else+ {+ match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char2, start);+ JUMPHERE(match);+ }+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && offset > 0)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-(offset + 1)));+ jumpto_if_not_utf_char_start(compiler, TMP1, start);+ }+#endif++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset + 1));++if (common->mode != PCRE2_JIT_COMPLETE)+ JUMPHERE(partial_quit);++if (has_match_end)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+}++static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_label *start;+struct sljit_jump *match;+fast_forward_char_data chars[MAX_N_CHARS];+sljit_s32 offset;+PCRE2_UCHAR mask;+PCRE2_UCHAR *char_set, *char_set_end;+int i, max, from;+int range_right = -1, range_len;+sljit_u8 *update_table = NULL;+BOOL in_range;+sljit_u32 rec_count;++for (i = 0; i < MAX_N_CHARS; i++)+ {+ chars[i].count = 0;+ chars[i].last_count = 0;+ }++rec_count = 10000;+max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count);++if (max < 1)+ return FALSE;++/* Convert last_count to priority. */+for (i = 0; i < max; i++)+ {+ SLJIT_ASSERT(chars[i].count > 0 && chars[i].last_count <= chars[i].count);++ if (chars[i].count == 1)+ {+ chars[i].last_count = (chars[i].last_count == 1) ? 7 : 5;+ /* Simplifies algorithms later. */+ chars[i].chars[1] = chars[i].chars[0];+ }+ else if (chars[i].count == 2)+ {+ SLJIT_ASSERT(chars[i].chars[0] != chars[i].chars[1]);++ if (is_powerof2(chars[i].chars[0] ^ chars[i].chars[1]))+ chars[i].last_count = (chars[i].last_count == 2) ? 6 : 4;+ else+ chars[i].last_count = (chars[i].last_count == 2) ? 3 : 2;+ }+ else+ chars[i].last_count = (chars[i].count == 255) ? 0 : 1;+ }++#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD+if (JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD && check_fast_forward_char_pair_simd(common, chars, max))+ return TRUE;+#endif++in_range = FALSE;+/* Prevent compiler "uninitialized" warning */+from = 0;+range_len = 4 /* minimum length */ - 1;+for (i = 0; i <= max; i++)+ {+ if (in_range && (i - from) > range_len && (chars[i - 1].count < 255))+ {+ range_len = i - from;+ range_right = i - 1;+ }++ if (i < max && chars[i].count < 255)+ {+ SLJIT_ASSERT(chars[i].count > 0);+ if (!in_range)+ {+ in_range = TRUE;+ from = i;+ }+ }+ else+ in_range = FALSE;+ }++if (range_right >= 0)+ {+ update_table = (sljit_u8 *)allocate_read_only_data(common, 256);+ if (update_table == NULL)+ return TRUE;+ memset(update_table, IN_UCHARS(range_len), 256);++ for (i = 0; i < range_len; i++)+ {+ SLJIT_ASSERT(chars[range_right - i].count > 0 && chars[range_right - i].count < 255);++ char_set = chars[range_right - i].chars;+ char_set_end = char_set + chars[range_right - i].count;+ do+ {+ if (update_table[(*char_set) & 0xff] > IN_UCHARS(i))+ update_table[(*char_set) & 0xff] = IN_UCHARS(i);+ char_set++;+ }+ while (char_set < char_set_end);+ }+ }++offset = -1;+/* Scan forward. */+for (i = 0; i < max; i++)+ {+ if (range_right == i)+ continue;++ if (offset == -1)+ {+ if (chars[i].last_count >= 2)+ offset = i;+ }+ else if (chars[offset].last_count < chars[i].last_count)+ offset = i;+ }++SLJIT_ASSERT(offset == -1 || (chars[offset].count >= 1 && chars[offset].count <= 2));++if (range_right < 0)+ {+ if (offset < 0)+ return FALSE;+ /* Works regardless the value is 1 or 2. */+ fast_forward_first_char2(common, chars[offset].chars[0], chars[offset].chars[1], offset);+ return TRUE;+ }++SLJIT_ASSERT(range_right != offset);++if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);+ OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0);+ CMOV(SLJIT_GREATER, STR_END, TMP1, 0);+ }+else+ {+ OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));+ }++SLJIT_ASSERT(range_right >= 0);++if (!HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);++start = LABEL();+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));++#if PCRE2_CODE_UNIT_WIDTH == 8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));+#else+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1);+#endif++if (!HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);+else+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start);++if (offset >= 0)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offset));+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ if (chars[offset].count == 1)+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0], start);+ else+ {+ mask = chars[offset].chars[0] ^ chars[offset].chars[1];+ if (is_powerof2(mask))+ {+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0] | mask, start);+ }+ else+ {+ match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0]);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[1], start);+ JUMPHERE(match);+ }+ }+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && offset != 0)+ {+ if (offset < 0)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ }+ else+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));++ jumpto_if_not_utf_char_start(compiler, TMP1, start);++ if (offset < 0)+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ }+#endif++if (offset >= 0)+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+else+ OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));+return TRUE;+}++static SLJIT_INLINE void fast_forward_first_char(compiler_common *common)+{+PCRE2_UCHAR first_char = (PCRE2_UCHAR)(common->re->first_codeunit);+PCRE2_UCHAR oc;++oc = first_char;+if ((common->re->flags & PCRE2_FIRSTCASELESS) != 0)+ {+ oc = TABLE_GET(first_char, common->fcc, first_char);+#if defined SUPPORT_UNICODE+ if (first_char > 127 && (common->utf || common->ucp))+ oc = UCD_OTHERCASE(first_char);+#endif+ }++fast_forward_first_char2(common, first_char, oc, 0);+}++static SLJIT_INLINE void fast_forward_newline(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_label *loop;+struct sljit_jump *lastchar = NULL;+struct sljit_jump *firstchar;+struct sljit_jump *quit = NULL;+struct sljit_jump *foundcr = NULL;+struct sljit_jump *notfoundnl;+jump_list *newline = NULL;++if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ }++if (common->nltype == NLTYPE_FIXED && common->newline > 255)+ {+#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD+ if (JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD && common->mode == PCRE2_JIT_COMPLETE)+ {+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);++ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_NOT_EQUAL);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);++ fast_forward_char_pair_simd(common, 1, common->newline & 0xff, common->newline & 0xff, 0, (common->newline >> 8) & 0xff, (common->newline >> 8) & 0xff);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+ }+ else+#endif /* JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD */+ {+ lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);++ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++ loop = LABEL();+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);+ CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);++ JUMPHERE(quit);+ JUMPHERE(lastchar);+ }++ JUMPHERE(firstchar);++ if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+ return;+ }++if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));+ }+else+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));++/* Example: match /^/ to \r\n from offset 1. */+firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);++if (common->nltype == NLTYPE_ANY)+ move_back(common, NULL, FALSE);+else+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++loop = LABEL();+common->ff_newline_shortcut = loop;++#ifdef JIT_HAS_FAST_FORWARD_CHAR_SIMD+if (JIT_HAS_FAST_FORWARD_CHAR_SIMD && (common->nltype == NLTYPE_FIXED || common->nltype == NLTYPE_ANYCRLF))+ {+ if (common->nltype == NLTYPE_ANYCRLF)+ {+ fast_forward_char_simd(common, CHAR_CR, CHAR_LF, 0);+ if (common->mode != PCRE2_JIT_COMPLETE)+ lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ quit = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);+ }+ else+ {+ fast_forward_char_simd(common, common->newline, common->newline, 0);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ if (common->mode != PCRE2_JIT_COMPLETE)+ {+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);+ CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);+ }+ }+ }+else+#endif /* JIT_HAS_FAST_FORWARD_CHAR_SIMD */+ {+ read_char(common, common->nlmin, common->nlmax, NULL, READ_CHAR_NEWLINE);+ lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)+ foundcr = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);+ check_newlinechar(common, common->nltype, &newline, FALSE);+ set_jumps(newline, loop);+ }++if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)+ {+ if (quit == NULL)+ {+ quit = JUMP(SLJIT_JUMP);+ JUMPHERE(foundcr);+ }++ notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);+#endif+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ JUMPHERE(notfoundnl);+ JUMPHERE(quit);+ }++if (lastchar)+ JUMPHERE(lastchar);+JUMPHERE(firstchar);++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+}++static BOOL optimize_class(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks);++static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common)+{+DEFINE_COMPILER;+const sljit_u8 *start_bits = common->re->start_bitmap;+struct sljit_label *start;+struct sljit_jump *partial_quit;+#if PCRE2_CODE_UNIT_WIDTH != 8+struct sljit_jump *found = NULL;+#endif+jump_list *matches = NULL;++if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0);+ CMOV(SLJIT_GREATER, STR_END, TMP1, 0);+ }++start = LABEL();++partial_quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit);++OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (!optimize_class(common, start_bits, (start_bits[31] & 0x80) != 0, FALSE, &matches))+ {+#if PCRE2_CODE_UNIT_WIDTH != 8+ if ((start_bits[31] & 0x80) != 0)+ found = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 255);+ else+ CMPTO(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 255, start);+#elif defined SUPPORT_UNICODE+ if (common->utf && is_char7_bitset(start_bits, FALSE))+ CMPTO(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 127, start);+#endif+ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);+ if (!HAS_VIRTUAL_REGISTERS)+ {+ OP2(SLJIT_SHL, TMP3, 0, SLJIT_IMM, 1, TMP2, 0);+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP3, 0);+ }+ else+ {+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);+ }+ JUMPTO(SLJIT_ZERO, start);+ }+else+ set_jumps(matches, start);++#if PCRE2_CODE_UNIT_WIDTH != 8+if (found != NULL)+ JUMPHERE(found);+#endif++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (common->mode != PCRE2_JIT_COMPLETE)+ JUMPHERE(partial_quit);++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0);+}++static SLJIT_INLINE jump_list *search_requested_char(compiler_common *common, PCRE2_UCHAR req_char, BOOL caseless, BOOL has_firstchar)+{+DEFINE_COMPILER;+struct sljit_label *loop;+struct sljit_jump *toolong;+struct sljit_jump *already_found;+struct sljit_jump *found;+struct sljit_jump *found_oc = NULL;+jump_list *not_found = NULL;+sljit_u32 oc, bit;++SLJIT_ASSERT(common->req_char_ptr != 0);+OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(REQ_CU_MAX) * 100);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr);+toolong = CMP(SLJIT_LESS, TMP2, 0, STR_END, 0);+already_found = CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0);++if (has_firstchar)+ OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+else+ OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);++oc = req_char;+if (caseless)+ {+ oc = TABLE_GET(req_char, common->fcc, req_char);+#if defined SUPPORT_UNICODE+ if (req_char > 127 && (common->utf || common->ucp))+ oc = UCD_OTHERCASE(req_char);+#endif+ }++#ifdef JIT_HAS_FAST_REQUESTED_CHAR_SIMD+if (JIT_HAS_FAST_REQUESTED_CHAR_SIMD)+ {+ not_found = fast_requested_char_simd(common, req_char, oc);+ }+else+#endif+ {+ loop = LABEL();+ add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));++ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0);++ if (req_char == oc)+ found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char);+ else+ {+ bit = req_char ^ oc;+ if (is_powerof2(bit))+ {+ OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);+ found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit);+ }+ else+ {+ found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char);+ found_oc = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, oc);+ }+ }+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPTO(SLJIT_JUMP, loop);++ JUMPHERE(found);+ if (found_oc)+ JUMPHERE(found_oc);+ }++OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, TMP1, 0);++JUMPHERE(already_found);+JUMPHERE(toolong);+return not_found;+}++static void do_revertframes(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_label *mainloop;++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);+GET_LOCAL_BASE(TMP1, 0, 0);++/* Drop frames until we reach STACK_TOP. */+mainloop = LABEL();+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -sizeof(sljit_sw));+jump = CMP(SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0);++OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);+if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw)));+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -(3 * sizeof(sljit_sw)));+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));+ }+else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw)));+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(3 * sizeof(sljit_sw)));+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0);+ GET_LOCAL_BASE(TMP1, 0, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP3, 0);+ }+JUMPTO(SLJIT_JUMP, mainloop);++JUMPHERE(jump);+jump = CMP(SLJIT_NOT_ZERO /* SIG_LESS */, TMP2, 0, SLJIT_IMM, 0);+/* End of reverting values. */+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);++JUMPHERE(jump);+OP1(SLJIT_NEG, TMP2, 0, TMP2, 0);+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);+if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw)));+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));+ }+else+ {+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw)));+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP3, 0);+ }+JUMPTO(SLJIT_JUMP, mainloop);+}++static void check_wordboundary(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_jump *skipread;+jump_list *skipread_list = NULL;+#ifdef SUPPORT_UNICODE+struct sljit_label *valid_utf;+jump_list *invalid_utf1 = NULL;+#endif /* SUPPORT_UNICODE */+jump_list *invalid_utf2 = NULL;+#if PCRE2_CODE_UNIT_WIDTH != 8 || defined SUPPORT_UNICODE+struct sljit_jump *jump;+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 || SUPPORT_UNICODE */++SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);++sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);+/* Get type of the previous char, and put it to TMP3. */+OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);+skipread = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);++#ifdef SUPPORT_UNICODE+if (common->invalid_utf)+ {+ peek_char_back(common, READ_CHAR_MAX, &invalid_utf1);++ if (common->mode != PCRE2_JIT_COMPLETE)+ {+ OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);+ move_back(common, NULL, TRUE);+ check_start_used_ptr(common);+ OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);+ }+ }+else+#endif /* SUPPORT_UNICODE */+ {+ if (common->mode == PCRE2_JIT_COMPLETE)+ peek_char_back(common, READ_CHAR_MAX, NULL);+ else+ {+ move_back(common, NULL, TRUE);+ check_start_used_ptr(common);+ read_char(common, 0, READ_CHAR_MAX, NULL, READ_CHAR_UPDATE_STR_PTR);+ }+ }++/* Testing char type. */+#ifdef SUPPORT_UNICODE+if (common->ucp)+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);+ jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);+ add_jump(compiler, &common->getucdtype, JUMP(SLJIT_FAST_CALL));+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);+ JUMPHERE(jump);+ OP1(SLJIT_MOV, TMP3, 0, TMP2, 0);+ }+else+#endif /* SUPPORT_UNICODE */+ {+#if PCRE2_CODE_UNIT_WIDTH != 8+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+#elif defined SUPPORT_UNICODE+ /* Here TMP3 has already been zeroed. */+ jump = NULL;+ if (common->utf)+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);+ OP2(SLJIT_AND, TMP3, 0, TMP1, 0, SLJIT_IMM, 1);+#if PCRE2_CODE_UNIT_WIDTH != 8+ JUMPHERE(jump);+#elif defined SUPPORT_UNICODE+ if (jump != NULL)+ JUMPHERE(jump);+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ }+JUMPHERE(skipread);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);+check_str_end(common, &skipread_list);+peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, &invalid_utf2);++/* Testing char type. This is a code duplication. */+#ifdef SUPPORT_UNICODE++valid_utf = LABEL();++if (common->ucp)+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);+ jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);+ add_jump(compiler, &common->getucdtype, JUMP(SLJIT_FAST_CALL));+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);+ JUMPHERE(jump);+ }+else+#endif /* SUPPORT_UNICODE */+ {+#if PCRE2_CODE_UNIT_WIDTH != 8+ /* TMP2 may be destroyed by peek_char. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+#elif defined SUPPORT_UNICODE+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);+ jump = NULL;+ if (common->utf)+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+#endif+ OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);+ OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);+#if PCRE2_CODE_UNIT_WIDTH != 8+ JUMPHERE(jump);+#elif defined SUPPORT_UNICODE+ if (jump != NULL)+ JUMPHERE(jump);+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ }+set_jumps(skipread_list, LABEL());++OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+OP2(SLJIT_XOR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, TMP3, 0);+OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);++#ifdef SUPPORT_UNICODE+if (common->invalid_utf)+ {+ set_jumps(invalid_utf1, LABEL());++ peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, NULL);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR, valid_utf);++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, -1);+ OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);++ set_jumps(invalid_utf2, LABEL());+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ OP1(SLJIT_MOV, TMP2, 0, TMP3, 0);+ OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);+ }+#endif /* SUPPORT_UNICODE */+}++static BOOL optimize_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)+{+/* May destroy TMP1. */+DEFINE_COMPILER;+int ranges[MAX_CLASS_RANGE_SIZE];+sljit_u8 bit, cbit, all;+int i, byte, length = 0;++bit = bits[0] & 0x1;+/* All bits will be zero or one (since bit is zero or one). */+all = -bit;++for (i = 0; i < 256; )+ {+ byte = i >> 3;+ if ((i & 0x7) == 0 && bits[byte] == all)+ i += 8;+ else+ {+ cbit = (bits[byte] >> (i & 0x7)) & 0x1;+ if (cbit != bit)+ {+ if (length >= MAX_CLASS_RANGE_SIZE)+ return FALSE;+ ranges[length] = i;+ length++;+ bit = cbit;+ all = -cbit;+ }+ i++;+ }+ }++if (((bit == 0) && nclass) || ((bit == 1) && !nclass))+ {+ if (length >= MAX_CLASS_RANGE_SIZE)+ return FALSE;+ ranges[length] = 256;+ length++;+ }++if (length < 0 || length > 4)+ return FALSE;++bit = bits[0] & 0x1;+if (invert) bit ^= 0x1;++/* No character is accepted. */+if (length == 0 && bit == 0)+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));++switch(length)+ {+ case 0:+ /* When bit != 0, all characters are accepted. */+ return TRUE;++ case 1:+ add_jump(compiler, backtracks, CMP(bit == 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));+ return TRUE;++ case 2:+ if (ranges[0] + 1 != ranges[1])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));+ }+ else+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));+ return TRUE;++ case 3:+ if (bit != 0)+ {+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));+ if (ranges[0] + 1 != ranges[1])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));+ return TRUE;+ }++ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[0]));+ if (ranges[1] + 1 != ranges[2])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1]);+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1]));+ return TRUE;++ case 4:+ if ((ranges[1] - ranges[0]) == (ranges[3] - ranges[2])+ && (ranges[0] | (ranges[2] - ranges[0])) == ranges[2]+ && (ranges[1] & (ranges[2] - ranges[0])) == 0+ && is_powerof2(ranges[2] - ranges[0]))+ {+ SLJIT_ASSERT((ranges[0] & (ranges[2] - ranges[0])) == 0 && (ranges[2] & ranges[3] & (ranges[2] - ranges[0])) != 0);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[0]);+ if (ranges[2] + 1 != ranges[3])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]);+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));+ }+ else+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));+ return TRUE;+ }++ if (bit != 0)+ {+ i = 0;+ if (ranges[0] + 1 != ranges[1])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));+ i = ranges[0];+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));++ if (ranges[2] + 1 != ranges[3])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - i);+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2] - i));+ return TRUE;+ }++ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[0]));+ if (ranges[1] + 1 != ranges[2])+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]);+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));+ return TRUE;++ default:+ SLJIT_UNREACHABLE();+ return FALSE;+ }+}++static BOOL optimize_class_chars(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)+{+/* May destroy TMP1. */+DEFINE_COMPILER;+uint16_t char_list[MAX_CLASS_CHARS_SIZE];+uint8_t byte;+sljit_s32 type;+int i, j, k, len, c;++if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV))+ return FALSE;++len = 0;++for (i = 0; i < 32; i++)+ {+ byte = bits[i];++ if (nclass)+ byte = ~byte;++ j = 0;+ while (byte != 0)+ {+ if (byte & 0x1)+ {+ c = i * 8 + j;++ k = len;++ if ((c & 0x20) != 0)+ {+ for (k = 0; k < len; k++)+ if (char_list[k] == c - 0x20)+ {+ char_list[k] |= 0x120;+ break;+ }+ }++ if (k == len)+ {+ if (len >= MAX_CLASS_CHARS_SIZE)+ return FALSE;++ char_list[len++] = (uint16_t) c;+ }+ }++ byte >>= 1;+ j++;+ }+ }++if (len == 0) return FALSE; /* Should never occur, but stops analyzers complaining. */++i = 0;+j = 0;++if (char_list[0] == 0)+ {+ i++;+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_ZERO);+ }+else+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);++while (i < len)+ {+ if ((char_list[i] & 0x100) != 0)+ j++;+ else+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_list[i]);+ CMOV(SLJIT_ZERO, TMP2, TMP1, 0);+ }+ i++;+ }++if (j != 0)+ {+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x20);++ for (i = 0; i < len; i++)+ if ((char_list[i] & 0x100) != 0)+ {+ j--;+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_list[i] & 0xff);+ CMOV(SLJIT_ZERO, TMP2, TMP1, 0);+ }+ }++if (invert)+ nclass = !nclass;++type = nclass ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;+add_jump(compiler, backtracks, CMP(type, TMP2, 0, SLJIT_IMM, 0));+return TRUE;+}++static BOOL optimize_class(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)+{+/* May destroy TMP1. */+if (optimize_class_ranges(common, bits, nclass, invert, backtracks))+ return TRUE;+return optimize_class_chars(common, bits, nclass, invert, backtracks);+}++static void check_anynewline(compiler_common *common)+{+/* Check whether TMP1 contains a newline character. TMP2 destroyed. */+DEFINE_COMPILER;++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);+OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+#endif+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);+#if PCRE2_CODE_UNIT_WIDTH == 8+ }+#endif+#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);+OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void check_hspace(compiler_common *common)+{+/* Check whether TMP1 contains a newline character. TMP2 destroyed. */+DEFINE_COMPILER;++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+#endif+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);+#if PCRE2_CODE_UNIT_WIDTH == 8+ }+#endif+#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void check_vspace(compiler_common *common)+{+/* Check whether TMP1 contains a newline character. TMP2 destroyed. */+DEFINE_COMPILER;++sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);++OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);+OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);+OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utf)+ {+#endif+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);+#if PCRE2_CODE_UNIT_WIDTH == 8+ }+#endif+#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */+OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);++OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);+}++static void do_casefulcmp(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_label *label;+int char1_reg;+int char2_reg;++if (HAS_VIRTUAL_REGISTERS)+ {+ char1_reg = STR_END;+ char2_reg = STACK_TOP;+ }+else+ {+ char1_reg = TMP3;+ char2_reg = RETURN_ADDR;+ }++sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++if (char1_reg == STR_END)+ {+ OP1(SLJIT_MOV, TMP3, 0, char1_reg, 0);+ OP1(SLJIT_MOV, RETURN_ADDR, 0, char2_reg, 0);+ }++if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)+ {+ label = LABEL();+ sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));+ sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPTO(SLJIT_NOT_ZERO, label);++ JUMPHERE(jump);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ }+else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ label = LABEL();+ sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));+ sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPTO(SLJIT_NOT_ZERO, label);++ JUMPHERE(jump);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ }+else+ {+ label = LABEL();+ OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);+ OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+ JUMPTO(SLJIT_NOT_ZERO, label);++ JUMPHERE(jump);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ }++if (char1_reg == STR_END)+ {+ OP1(SLJIT_MOV, char1_reg, 0, TMP3, 0);+ OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0);+ }++OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);+}++static void do_caselesscmp(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_jump *jump;+struct sljit_label *label;+int char1_reg = STR_END;+int char2_reg;+int lcc_table;+int opt_type = 0;++if (HAS_VIRTUAL_REGISTERS)+ {+ char2_reg = STACK_TOP;+ lcc_table = STACK_LIMIT;+ }+else+ {+ char2_reg = RETURN_ADDR;+ lcc_table = TMP3;+ }++if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)+ opt_type = 1;+else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)+ opt_type = 2;++sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, char1_reg, 0);++if (char2_reg == STACK_TOP)+ {+ OP1(SLJIT_MOV, TMP3, 0, char2_reg, 0);+ OP1(SLJIT_MOV, RETURN_ADDR, 0, lcc_table, 0);+ }++OP1(SLJIT_MOV, lcc_table, 0, SLJIT_IMM, common->lcc);++if (opt_type == 1)+ {+ label = LABEL();+ sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));+ sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ }+else if (opt_type == 2)+ {+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ label = LABEL();+ sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));+ sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ }+else+ {+ label = LABEL();+ OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);+ OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));+ }++#if PCRE2_CODE_UNIT_WIDTH != 8+jump = CMP(SLJIT_GREATER, char1_reg, 0, SLJIT_IMM, 255);+#endif+OP1(SLJIT_MOV_U8, char1_reg, 0, SLJIT_MEM2(lcc_table, char1_reg), 0);+#if PCRE2_CODE_UNIT_WIDTH != 8+JUMPHERE(jump);+jump = CMP(SLJIT_GREATER, char2_reg, 0, SLJIT_IMM, 255);+#endif+OP1(SLJIT_MOV_U8, char2_reg, 0, SLJIT_MEM2(lcc_table, char2_reg), 0);+#if PCRE2_CODE_UNIT_WIDTH != 8+JUMPHERE(jump);+#endif++if (opt_type == 0)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);+OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));+JUMPTO(SLJIT_NOT_ZERO, label);++JUMPHERE(jump);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);++if (opt_type == 2)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++if (char2_reg == STACK_TOP)+ {+ OP1(SLJIT_MOV, char2_reg, 0, TMP3, 0);+ OP1(SLJIT_MOV, lcc_table, 0, RETURN_ADDR, 0);+ }++OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);+OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);+}++static PCRE2_SPTR byte_sequence_compare(compiler_common *common, BOOL caseless, PCRE2_SPTR cc,+ compare_context *context, jump_list **backtracks)+{+DEFINE_COMPILER;+unsigned int othercasebit = 0;+PCRE2_SPTR othercasechar = NULL;+#ifdef SUPPORT_UNICODE+int utflength;+#endif++if (caseless && char_has_othercase(common, cc))+ {+ othercasebit = char_get_othercase_bit(common, cc);+ SLJIT_ASSERT(othercasebit);+ /* Extracting bit difference info. */+#if PCRE2_CODE_UNIT_WIDTH == 8+ othercasechar = cc + (othercasebit >> 8);+ othercasebit &= 0xff;+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ /* Note that this code only handles characters in the BMP. If there+ ever are characters outside the BMP whose othercase differs in only one+ bit from itself (there currently are none), this code will need to be+ revised for PCRE2_CODE_UNIT_WIDTH == 32. */+ othercasechar = cc + (othercasebit >> 9);+ if ((othercasebit & 0x100) != 0)+ othercasebit = (othercasebit & 0xff) << 8;+ else+ othercasebit &= 0xff;+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+ }++if (context->sourcereg == -1)+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED+ if (context->length >= 4)+ OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);+ else if (context->length >= 2)+ OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);+ else+#endif+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);+#elif PCRE2_CODE_UNIT_WIDTH == 16+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED+ if (context->length >= 4)+ OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);+ else+#endif+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);+#elif PCRE2_CODE_UNIT_WIDTH == 32+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */+ context->sourcereg = TMP2;+ }++#ifdef SUPPORT_UNICODE+utflength = 1;+if (common->utf && HAS_EXTRALEN(*cc))+ utflength += GET_EXTRALEN(*cc);++do+ {+#endif++ context->length -= IN_UCHARS(1);+#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)++ /* Unaligned read is supported. */+ if (othercasebit != 0 && othercasechar == cc)+ {+ context->c.asuchars[context->ucharptr] = *cc | othercasebit;+ context->oc.asuchars[context->ucharptr] = othercasebit;+ }+ else+ {+ context->c.asuchars[context->ucharptr] = *cc;+ context->oc.asuchars[context->ucharptr] = 0;+ }+ context->ucharptr++;++#if PCRE2_CODE_UNIT_WIDTH == 8+ if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1))+#else+ if (context->ucharptr >= 2 || context->length == 0)+#endif+ {+ if (context->length >= 4)+ OP1(SLJIT_MOV_S32, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);+ else if (context->length >= 2)+ OP1(SLJIT_MOV_U16, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);+#if PCRE2_CODE_UNIT_WIDTH == 8+ else if (context->length >= 1)+ OP1(SLJIT_MOV_U8, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;++ switch(context->ucharptr)+ {+ case 4 / sizeof(PCRE2_UCHAR):+ if (context->oc.asint != 0)+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));+ break;++ case 2 / sizeof(PCRE2_UCHAR):+ if (context->oc.asushort != 0)+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));+ break;++#if PCRE2_CODE_UNIT_WIDTH == 8+ case 1:+ if (context->oc.asbyte != 0)+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));+ break;+#endif++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ context->ucharptr = 0;+ }++#else++ /* Unaligned read is unsupported or in 32 bit mode. */+ if (context->length >= 1)+ OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);++ context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;++ if (othercasebit != 0 && othercasechar == cc)+ {+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));+ }+ else+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));++#endif++ cc++;+#ifdef SUPPORT_UNICODE+ utflength--;+ }+while (utflength > 0);+#endif++return cc;+}++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8++#define SET_TYPE_OFFSET(value) \+ if ((value) != typeoffset) \+ { \+ if ((value) < typeoffset) \+ OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \+ else \+ OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \+ } \+ typeoffset = (value);++#define SET_CHAR_OFFSET(value) \+ if ((value) != charoffset) \+ { \+ if ((value) < charoffset) \+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(charoffset - (value))); \+ else \+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)((value) - charoffset)); \+ } \+ charoffset = (value);++static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr);++static void compile_xclass_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)+{+DEFINE_COMPILER;+jump_list *found = NULL;+jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks;+sljit_uw c, charoffset, max = 256, min = READ_CHAR_MAX;+struct sljit_jump *jump = NULL;+PCRE2_SPTR ccbegin;+int compares, invertcmp, numberofcmps;+#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)+BOOL utf = common->utf;+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */++#ifdef SUPPORT_UNICODE+BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;+BOOL charsaved = FALSE;+int typereg = TMP1;+const sljit_u32 *other_cases;+sljit_uw typeoffset;+#endif /* SUPPORT_UNICODE */++/* Scanning the necessary info. */+cc++;+ccbegin = cc;+compares = 0;++if (cc[-1] & XCL_MAP)+ {+ min = 0;+ cc += 32 / sizeof(PCRE2_UCHAR);+ }++while (*cc != XCL_END)+ {+ compares++;+ if (*cc == XCL_SINGLE)+ {+ cc ++;+ GETCHARINCTEST(c, cc);+ if (c > max) max = c;+ if (c < min) min = c;+#ifdef SUPPORT_UNICODE+ needschar = TRUE;+#endif /* SUPPORT_UNICODE */+ }+ else if (*cc == XCL_RANGE)+ {+ cc ++;+ GETCHARINCTEST(c, cc);+ if (c < min) min = c;+ GETCHARINCTEST(c, cc);+ if (c > max) max = c;+#ifdef SUPPORT_UNICODE+ needschar = TRUE;+#endif /* SUPPORT_UNICODE */+ }+#ifdef SUPPORT_UNICODE+ else+ {+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);+ cc++;+ if (*cc == PT_CLIST)+ {+ other_cases = PRIV(ucd_caseless_sets) + cc[1];+ while (*other_cases != NOTACHAR)+ {+ if (*other_cases > max) max = *other_cases;+ if (*other_cases < min) min = *other_cases;+ other_cases++;+ }+ }+ else+ {+ max = READ_CHAR_MAX;+ min = 0;+ }++ switch(*cc)+ {+ case PT_ANY:+ /* Any either accepts everything or ignored. */+ if (cc[-1] == XCL_PROP)+ {+ compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE);+ if (list == backtracks)+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ return;+ }+ break;++ case PT_LAMP:+ case PT_GC:+ case PT_PC:+ case PT_ALNUM:+ needstype = TRUE;+ break;++ case PT_SC:+ needsscript = TRUE;+ break;++ case PT_SPACE:+ case PT_PXSPACE:+ case PT_WORD:+ case PT_PXGRAPH:+ case PT_PXPRINT:+ case PT_PXPUNCT:+ needstype = TRUE;+ needschar = TRUE;+ break;++ case PT_CLIST:+ case PT_UCNC:+ needschar = TRUE;+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ cc += 2;+ }+#endif /* SUPPORT_UNICODE */+ }+SLJIT_ASSERT(compares > 0);++/* We are not necessary in utf mode even in 8 bit mode. */+cc = ccbegin;+if ((cc[-1] & XCL_NOT) != 0)+ read_char(common, min, max, backtracks, READ_CHAR_UPDATE_STR_PTR);+else+ {+#ifdef SUPPORT_UNICODE+ read_char(common, min, max, (needstype || needsscript) ? backtracks : NULL, 0);+#else /* !SUPPORT_UNICODE */+ read_char(common, min, max, NULL, 0);+#endif /* SUPPORT_UNICODE */+ }++if ((cc[-1] & XCL_HASPROP) == 0)+ {+ if ((cc[-1] & XCL_MAP) != 0)+ {+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+ if (!optimize_class(common, (const sljit_u8 *)cc, (((const sljit_u8 *)cc)[31] & 0x80) != 0, TRUE, &found))+ {+ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);+ add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO));+ }++ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ JUMPHERE(jump);++ cc += 32 / sizeof(PCRE2_UCHAR);+ }+ else+ {+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, min);+ add_jump(compiler, (cc[-1] & XCL_NOT) == 0 ? backtracks : &found, CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, max - min));+ }+ }+else if ((cc[-1] & XCL_MAP) != 0)+ {+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);+#ifdef SUPPORT_UNICODE+ charsaved = TRUE;+#endif /* SUPPORT_UNICODE */+ if (!optimize_class(common, (const sljit_u8 *)cc, FALSE, TRUE, list))+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ jump = NULL;+ if (common->utf)+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);++ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);+ add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO));++#if PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf)+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ JUMPHERE(jump);+ }++ OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);+ cc += 32 / sizeof(PCRE2_UCHAR);+ }++#ifdef SUPPORT_UNICODE+if (needstype || needsscript)+ {+ if (needschar && !charsaved)+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);++#if PCRE2_CODE_UNIT_WIDTH == 32+ if (!common->utf)+ {+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);+ JUMPHERE(jump);+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */++ OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);+ OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));+ OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);++ /* Before anything else, we deal with scripts. */+ if (needsscript)+ {+ OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);++ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));++ ccbegin = cc;++ while (*cc != XCL_END)+ {+ if (*cc == XCL_SINGLE)+ {+ cc ++;+ GETCHARINCTEST(c, cc);+ }+ else if (*cc == XCL_RANGE)+ {+ cc ++;+ GETCHARINCTEST(c, cc);+ GETCHARINCTEST(c, cc);+ }+ else+ {+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);+ cc++;+ if (*cc == PT_SC)+ {+ compares--;+ invertcmp = (compares == 0 && list != backtracks);+ if (cc[-1] == XCL_NOTPROP)+ invertcmp ^= 0x1;+ jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]);+ add_jump(compiler, compares > 0 ? list : backtracks, jump);+ }+ cc += 2;+ }+ }++ cc = ccbegin;++ if (needstype)+ {+ /* TMP2 has already been shifted by 2 */+ if (!needschar)+ {+ OP2(SLJIT_ADD, TMP1, 0, TMP2, 0, TMP2, 0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);++ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));+ }+ else+ {+ OP2(SLJIT_ADD, TMP1, 0, TMP2, 0, TMP2, 0);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);++ OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);+ OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));+ typereg = RETURN_ADDR;+ }+ }+ else if (needschar)+ OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);+ }+ else if (needstype)+ {+ OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);++ if (!needschar)+ {+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);++ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));+ }+ else+ {+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);++ OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);+ OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));+ typereg = RETURN_ADDR;+ }+ }+ else if (needschar)+ OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);+ }+#endif /* SUPPORT_UNICODE */++/* Generating code. */+charoffset = 0;+numberofcmps = 0;+#ifdef SUPPORT_UNICODE+typeoffset = 0;+#endif /* SUPPORT_UNICODE */++while (*cc != XCL_END)+ {+ compares--;+ invertcmp = (compares == 0 && list != backtracks);+ jump = NULL;++ if (*cc == XCL_SINGLE)+ {+ cc ++;+ GETCHARINCTEST(c, cc);++ if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));+ OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ numberofcmps++;+ }+ else if (numberofcmps > 0)+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ numberofcmps = 0;+ }+ else+ {+ jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));+ numberofcmps = 0;+ }+ }+ else if (*cc == XCL_RANGE)+ {+ cc ++;+ GETCHARINCTEST(c, cc);+ SET_CHAR_OFFSET(c);+ GETCHARINCTEST(c, cc);++ if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))+ {+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));+ OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);+ numberofcmps++;+ }+ else if (numberofcmps > 0)+ {+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ numberofcmps = 0;+ }+ else+ {+ jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));+ numberofcmps = 0;+ }+ }+#ifdef SUPPORT_UNICODE+ else+ {+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);+ if (*cc == XCL_NOTPROP)+ invertcmp ^= 0x1;+ cc++;+ switch(*cc)+ {+ case PT_ANY:+ if (!invertcmp)+ jump = JUMP(SLJIT_JUMP);+ break;++ case PT_LAMP:+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ break;++ case PT_GC:+ c = PRIV(ucp_typerange)[(int)cc[1] * 2];+ SET_TYPE_OFFSET(c);+ jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c);+ break;++ case PT_PC:+ jump = CMP(SLJIT_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset);+ break;++ case PT_SC:+ compares++;+ /* Do nothing. */+ break;++ case PT_SPACE:+ case PT_PXSPACE:+ SET_CHAR_OFFSET(9);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);++ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ SET_TYPE_OFFSET(ucp_Zl);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ break;++ case PT_WORD:+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset));+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+ /* Fall through. */++ case PT_ALNUM:+ SET_TYPE_OFFSET(ucp_Ll);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);+ OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);+ SET_TYPE_OFFSET(ucp_Nd);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ break;++ case PT_CLIST:+ other_cases = PRIV(ucd_caseless_sets) + cc[1];++ /* At least three characters are required.+ Otherwise this case would be handled by the normal code path. */+ SLJIT_ASSERT(other_cases[0] != NOTACHAR && other_cases[1] != NOTACHAR && other_cases[2] != NOTACHAR);+ SLJIT_ASSERT(other_cases[0] < other_cases[1] && other_cases[1] < other_cases[2]);++ /* Optimizing character pairs, if their difference is power of 2. */+ if (is_powerof2(other_cases[1] ^ other_cases[0]))+ {+ if (charoffset == 0)+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);+ else+ {+ OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);+ OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);+ }+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+ other_cases += 2;+ }+ else if (is_powerof2(other_cases[2] ^ other_cases[1]))+ {+ if (charoffset == 0)+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[2] ^ other_cases[1]);+ else+ {+ OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);+ OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);+ }+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);++ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset));+ OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);++ other_cases += 3;+ }+ else+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+ }++ while (*other_cases != NOTACHAR)+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));+ OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);+ }+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ break;++ case PT_UCNC:+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ SET_CHAR_OFFSET(0xa0);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);+ SET_CHAR_OFFSET(0);+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0);+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_GREATER_EQUAL);+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ break;++ case PT_PXGRAPH:+ /* C and Z groups are the farthest two groups. */+ SET_TYPE_OFFSET(ucp_Ll);+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);++ jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);++ /* In case of ucp_Cf, we overwrite the result. */+ SET_CHAR_OFFSET(0x2066);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);++ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ JUMPHERE(jump);+ jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);+ break;++ case PT_PXPRINT:+ /* C and Z groups are the farthest two groups. */+ SET_TYPE_OFFSET(ucp_Ll);+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);++ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll);+ OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_NOT_EQUAL);++ jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);++ /* In case of ucp_Cf, we overwrite the result. */+ SET_CHAR_OFFSET(0x2066);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);++ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);+ OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);++ JUMPHERE(jump);+ jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);+ break;++ case PT_PXPUNCT:+ SET_TYPE_OFFSET(ucp_Sc);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);++ SET_CHAR_OFFSET(0);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f);+ OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL);++ SET_TYPE_OFFSET(ucp_Pc);+ OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc);+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);+ jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ cc += 2;+ }+#endif /* SUPPORT_UNICODE */++ if (jump != NULL)+ add_jump(compiler, compares > 0 ? list : backtracks, jump);+ }++if (found != NULL)+ set_jumps(found, LABEL());+}++#undef SET_TYPE_OFFSET+#undef SET_CHAR_OFFSET++#endif++static PCRE2_SPTR compile_simple_assertion_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks)+{+DEFINE_COMPILER;+int length;+struct sljit_jump *jump[4];+#ifdef SUPPORT_UNICODE+struct sljit_label *label;+#endif /* SUPPORT_UNICODE */++switch(type)+ {+ case OP_SOD:+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ else+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));+ return cc;++ case OP_SOM:+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));+ }+ else+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));+ return cc;++ case OP_NOT_WORD_BOUNDARY:+ case OP_WORD_BOUNDARY:+ add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));+#ifdef SUPPORT_UNICODE+ if (common->invalid_utf)+ {+ add_jump(compiler, backtracks, CMP((type == OP_NOT_WORD_BOUNDARY) ? SLJIT_NOT_EQUAL : SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0));+ return cc;+ }+#endif /* SUPPORT_UNICODE */+ sljit_set_current_flags(compiler, SLJIT_SET_Z);+ add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_NOT_ZERO : SLJIT_ZERO));+ return cc;++ case OP_EODN:+ /* Requires rather complex checks. */+ jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+ if (common->nltype == NLTYPE_FIXED && common->newline > 255)+ {+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));+ else+ {+ jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0);+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);+ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_EQUAL);+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL));+ check_partial(common, TRUE);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ JUMPHERE(jump[1]);+ }+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));+ }+ else if (common->nltype == NLTYPE_FIXED)+ {+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));+ }+ else+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+ OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);+ jump[2] = JUMP(SLJIT_GREATER);+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL) /* LESS */);+ /* Equal. */+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ jump[3] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));++ JUMPHERE(jump[1]);+ if (common->nltype == NLTYPE_ANYCRLF)+ {+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, STR_END, 0));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));+ }+ else+ {+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);+ read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0));+ add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));+ sljit_set_current_flags(compiler, SLJIT_SET_Z);+ add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+ }+ JUMPHERE(jump[2]);+ JUMPHERE(jump[3]);+ }+ JUMPHERE(jump[0]);+ if (common->mode != PCRE2_JIT_COMPLETE)+ check_partial(common, TRUE);+ return cc;++ case OP_EOD:+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));+ if (common->mode != PCRE2_JIT_COMPLETE)+ check_partial(common, TRUE);+ return cc;++ case OP_DOLL:+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);+ }+ else+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));++ if (!common->endonly)+ compile_simple_assertion_matchingpath(common, OP_EODN, cc, backtracks);+ else+ {+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));+ check_partial(common, FALSE);+ }+ return cc;++ case OP_DOLLM:+ jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);+ }+ else+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));+ check_partial(common, FALSE);+ jump[0] = JUMP(SLJIT_JUMP);+ JUMPHERE(jump[1]);++ if (common->nltype == NLTYPE_FIXED && common->newline > 255)+ {+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0));+ else+ {+ jump[1] = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0);+ /* STR_PTR = STR_END - IN_UCHARS(1) */+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));+ check_partial(common, TRUE);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ JUMPHERE(jump[1]);+ }++ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));+ }+ else+ {+ peek_char(common, common->nlmax, TMP3, 0, NULL);+ check_newlinechar(common, common->nltype, backtracks, FALSE);+ }+ JUMPHERE(jump[0]);+ return cc;++ case OP_CIRC:+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));+ }+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));+ }+ return cc;++ case OP_CIRCM:+ /* TMP2 might be used by peek_char_back. */+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+ jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+ jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);+ }+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));+ jump[0] = JUMP(SLJIT_JUMP);+ JUMPHERE(jump[1]);++ if (!common->alt_circumflex)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++ if (common->nltype == NLTYPE_FIXED && common->newline > 255)+ {+ OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, TMP2, 0));+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));+ }+ else+ {+ peek_char_back(common, common->nlmax, backtracks);+ check_newlinechar(common, common->nltype, backtracks, FALSE);+ }+ JUMPHERE(jump[0]);+ return cc;++ case OP_REVERSE:+ length = GET(cc, 0);+ if (length == 0)+ return cc + LINK_SIZE;+ if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));+ }+ else+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));+#ifdef SUPPORT_UNICODE+ if (common->utf)+ {+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, length);+ label = LABEL();+ add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0));+ move_back(common, backtracks, FALSE);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);+ }+ else+#endif+ {+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0));+ }+ check_start_used_ptr(common);+ return cc + LINK_SIZE;+ }+SLJIT_UNREACHABLE();+return cc;+}++#ifdef SUPPORT_UNICODE++#if PCRE2_CODE_UNIT_WIDTH != 32++static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc)+{+PCRE2_SPTR start_subject = args->begin;+PCRE2_SPTR end_subject = args->end;+int lgb, rgb, ricount;+PCRE2_SPTR prevcc, endcc, bptr;+BOOL first = TRUE;+uint32_t c;++prevcc = cc;+endcc = NULL;+do+ {+ GETCHARINC(c, cc);+ rgb = UCD_GRAPHBREAK(c);++ if (first)+ {+ lgb = rgb;+ endcc = cc;+ first = FALSE;+ continue;+ }++ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)+ break;++ /* Not breaking between Regional Indicators is allowed only if there+ are an even number of preceding RIs. */++ if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)+ {+ ricount = 0;+ bptr = prevcc;++ /* bptr is pointing to the left-hand character */+ while (bptr > start_subject)+ {+ bptr--;+ BACKCHAR(bptr);+ GETCHAR(c, bptr);++ if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator)+ break;++ ricount++;+ }++ if ((ricount & 1) != 0) break; /* Grapheme break required */+ }++ /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this+ allows any number of them before a following Extended_Pictographic. */++ if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||+ lgb != ucp_gbExtended_Pictographic)+ lgb = rgb;++ prevcc = endcc;+ endcc = cc;+ }+while (cc < end_subject);++return endcc;+}++#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */++static PCRE2_SPTR SLJIT_FUNC do_extuni_utf_invalid(jit_arguments *args, PCRE2_SPTR cc)+{+PCRE2_SPTR start_subject = args->begin;+PCRE2_SPTR end_subject = args->end;+int lgb, rgb, ricount;+PCRE2_SPTR prevcc, endcc, bptr;+BOOL first = TRUE;+uint32_t c;++prevcc = cc;+endcc = NULL;+do+ {+ GETCHARINC_INVALID(c, cc, end_subject, break);+ rgb = UCD_GRAPHBREAK(c);++ if (first)+ {+ lgb = rgb;+ endcc = cc;+ first = FALSE;+ continue;+ }++ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)+ break;++ /* Not breaking between Regional Indicators is allowed only if there+ are an even number of preceding RIs. */++ if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)+ {+ ricount = 0;+ bptr = prevcc;++ /* bptr is pointing to the left-hand character */+ while (bptr > start_subject)+ {+ GETCHARBACK_INVALID(c, bptr, start_subject, break);++ if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator)+ break;++ ricount++;+ }++ if ((ricount & 1) != 0)+ break; /* Grapheme break required */+ }++ /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this+ allows any number of them before a following Extended_Pictographic. */++ if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||+ lgb != ucp_gbExtended_Pictographic)+ lgb = rgb;++ prevcc = endcc;+ endcc = cc;+ }+while (cc < end_subject);++return endcc;+}++static PCRE2_SPTR SLJIT_FUNC do_extuni_no_utf(jit_arguments *args, PCRE2_SPTR cc)+{+PCRE2_SPTR start_subject = args->begin;+PCRE2_SPTR end_subject = args->end;+int lgb, rgb, ricount;+PCRE2_SPTR bptr;+uint32_t c;++/* Patch by PH */+/* GETCHARINC(c, cc); */+c = *cc++;++#if PCRE2_CODE_UNIT_WIDTH == 32+if (c >= 0x110000)+ return NULL;+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */+lgb = UCD_GRAPHBREAK(c);++while (cc < end_subject)+ {+ c = *cc;+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c >= 0x110000)+ break;+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */+ rgb = UCD_GRAPHBREAK(c);++ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)+ break;++ /* Not breaking between Regional Indicators is allowed only if there+ are an even number of preceding RIs. */++ if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)+ {+ ricount = 0;+ bptr = cc - 1;++ /* bptr is pointing to the left-hand character */+ while (bptr > start_subject)+ {+ bptr--;+ c = *bptr;+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c >= 0x110000)+ break;+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */++ if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break;++ ricount++;+ }++ if ((ricount & 1) != 0)+ break; /* Grapheme break required */+ }++ /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this+ allows any number of them before a following Extended_Pictographic. */++ if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||+ lgb != ucp_gbExtended_Pictographic)+ lgb = rgb;++ cc++;+ }++return cc;+}++#endif /* SUPPORT_UNICODE */++static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr)+{+DEFINE_COMPILER;+int length;+unsigned int c, oc, bit;+compare_context context;+struct sljit_jump *jump[3];+jump_list *end_list;+#ifdef SUPPORT_UNICODE+PCRE2_UCHAR propdata[5];+#endif /* SUPPORT_UNICODE */++switch(type)+ {+ case OP_NOT_DIGIT:+ case OP_DIGIT:+ /* Digits are usually 0-9, so it is worth to optimize them. */+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_digit, FALSE))+ read_char7_type(common, backtracks, type == OP_NOT_DIGIT);+ else+#endif+ read_char8_type(common, backtracks, type == OP_NOT_DIGIT);+ /* Flip the starting bit in the negative case. */+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);+ add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO));+ return cc;++ case OP_NOT_WHITESPACE:+ case OP_WHITESPACE:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_space, FALSE))+ read_char7_type(common, backtracks, type == OP_NOT_WHITESPACE);+ else+#endif+ read_char8_type(common, backtracks, type == OP_NOT_WHITESPACE);+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);+ add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO));+ return cc;++ case OP_NOT_WORDCHAR:+ case OP_WORDCHAR:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_word, FALSE))+ read_char7_type(common, backtracks, type == OP_NOT_WORDCHAR);+ else+#endif+ read_char8_type(common, backtracks, type == OP_NOT_WORDCHAR);+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);+ add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO));+ return cc;++ case OP_ANY:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+ read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR);+ if (common->nltype == NLTYPE_FIXED && common->newline > 255)+ {+ jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);+ end_list = NULL;+ if (common->mode != PCRE2_JIT_PARTIAL_HARD)+ add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));+ else+ check_str_end(common, &end_list);++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));+ set_jumps(end_list, LABEL());+ JUMPHERE(jump[0]);+ }+ else+ check_newlinechar(common, common->nltype, backtracks, TRUE);+ return cc;++ case OP_ALLANY:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+#ifdef SUPPORT_UNICODE+ if (common->utf)+ {+ if (common->invalid_utf)+ {+ read_char(common, 0, READ_CHAR_MAX, backtracks, READ_CHAR_UPDATE_STR_PTR);+ return cc;+ }++#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+#if PCRE2_CODE_UNIT_WIDTH == 8+ jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+#elif PCRE2_CODE_UNIT_WIDTH == 16+ jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ JUMPHERE(jump[0]);+ return cc;+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */+ }+#endif /* SUPPORT_UNICODE */+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ return cc;++ case OP_ANYBYTE:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ return cc;++#ifdef SUPPORT_UNICODE+ case OP_NOTPROP:+ case OP_PROP:+ propdata[0] = XCL_HASPROP;+ propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;+ propdata[2] = cc[0];+ propdata[3] = cc[1];+ propdata[4] = XCL_END;+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+ compile_xclass_matchingpath(common, propdata, backtracks);+ return cc + 2;+#endif++ case OP_ANYNL:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+ read_char(common, common->bsr_nlmin, common->bsr_nlmax, NULL, 0);+ jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);+ /* We don't need to handle soft partial matching case. */+ end_list = NULL;+ if (common->mode != PCRE2_JIT_PARTIAL_HARD)+ add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));+ else+ check_str_end(common, &end_list);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ jump[2] = JUMP(SLJIT_JUMP);+ JUMPHERE(jump[0]);+ check_newlinechar(common, common->bsr_nltype, backtracks, FALSE);+ set_jumps(end_list, LABEL());+ JUMPHERE(jump[1]);+ JUMPHERE(jump[2]);+ return cc;++ case OP_NOT_HSPACE:+ case OP_HSPACE:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);++ if (type == OP_NOT_HSPACE)+ read_char(common, 0x9, 0x3000, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ read_char(common, 0x9, 0x3000, NULL, 0);++ add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));+ sljit_set_current_flags(compiler, SLJIT_SET_Z);+ add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));+ return cc;++ case OP_NOT_VSPACE:+ case OP_VSPACE:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);++ if (type == OP_NOT_VSPACE)+ read_char(common, 0xa, 0x2029, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ read_char(common, 0xa, 0x2029, NULL, 0);++ add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));+ sljit_set_current_flags(compiler, SLJIT_SET_Z);+ add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));+ return cc;++#ifdef SUPPORT_UNICODE+ case OP_EXTUNI:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);++ SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);+ OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);++#if PCRE2_CODE_UNIT_WIDTH != 32+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,+ common->utf ? (common->invalid_utf ? SLJIT_FUNC_OFFSET(do_extuni_utf_invalid) : SLJIT_FUNC_OFFSET(do_extuni_utf)) : SLJIT_FUNC_OFFSET(do_extuni_no_utf));+ if (common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));+#else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,+ common->invalid_utf ? SLJIT_FUNC_OFFSET(do_extuni_utf_invalid) : SLJIT_FUNC_OFFSET(do_extuni_no_utf));+ if (!common->utf || common->invalid_utf)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));+#endif++ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);++ if (common->mode == PCRE2_JIT_PARTIAL_HARD)+ {+ jump[0] = CMP(SLJIT_LESS, SLJIT_RETURN_REG, 0, STR_END, 0);+ /* Since we successfully read a char above, partial matching must occure. */+ check_partial(common, TRUE);+ JUMPHERE(jump[0]);+ }+ return cc;+#endif++ case OP_CHAR:+ case OP_CHARI:+ length = 1;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);+#endif++ if (check_str_ptr && common->mode != PCRE2_JIT_COMPLETE)+ detect_partial_match(common, backtracks);++ if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)+ {+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));+ if (length > 1 || (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE))+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));++ context.length = IN_UCHARS(length);+ context.sourcereg = -1;+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED+ context.ucharptr = 0;+#endif+ return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);+ }++#ifdef SUPPORT_UNICODE+ if (common->utf)+ {+ GETCHAR(c, cc);+ }+ else+#endif+ c = *cc;++ SLJIT_ASSERT(type == OP_CHARI && char_has_othercase(common, cc));++ if (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++ oc = char_othercase(common, c);+ read_char(common, c < oc ? c : oc, c > oc ? c : oc, NULL, 0);++ SLJIT_ASSERT(!is_powerof2(c ^ oc));++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV))+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);+ CMOV(SLJIT_EQUAL, TMP1, SLJIT_IMM, c);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c));+ }+ else+ {+ jump[0] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c);+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc));+ JUMPHERE(jump[0]);+ }+ return cc + length;++ case OP_NOT:+ case OP_NOTI:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);++ length = 1;+#ifdef SUPPORT_UNICODE+ if (common->utf)+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ c = *cc;+ if (c < 128 && !common->invalid_utf)+ {+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);+ if (type == OP_NOT || !char_has_othercase(common, cc))+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));+ else+ {+ /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20);+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20));+ }+ /* Skip the variable-length character. */+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ JUMPHERE(jump[0]);+ return cc + 1;+ }+ else+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ {+ GETCHARLEN(c, cc, length);+ }+ }+ else+#endif /* SUPPORT_UNICODE */+ c = *cc;++ if (type == OP_NOT || !char_has_othercase(common, cc))+ {+ read_char(common, c, c, backtracks, READ_CHAR_UPDATE_STR_PTR);+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));+ }+ else+ {+ oc = char_othercase(common, c);+ read_char(common, c < oc ? c : oc, c > oc ? c : oc, backtracks, READ_CHAR_UPDATE_STR_PTR);+ bit = c ^ oc;+ if (is_powerof2(bit))+ {+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));+ }+ else+ {+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, oc));+ }+ }+ return cc + length;++ case OP_CLASS:+ case OP_NCLASS:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255;+ if (type == OP_NCLASS)+ read_char(common, 0, bit, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ read_char(common, 0, bit, NULL, 0);+#else+ if (type == OP_NCLASS)+ read_char(common, 0, 255, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ read_char(common, 0, 255, NULL, 0);+#endif++ if (optimize_class(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks))+ return cc + 32 / sizeof(PCRE2_UCHAR);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ jump[0] = NULL;+ if (common->utf)+ {+ jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, bit);+ if (type == OP_CLASS)+ {+ add_jump(compiler, backtracks, jump[0]);+ jump[0] = NULL;+ }+ }+#elif PCRE2_CODE_UNIT_WIDTH != 8+ jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+ if (type == OP_CLASS)+ {+ add_jump(compiler, backtracks, jump[0]);+ jump[0] = NULL;+ }+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */++ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);+ add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ if (jump[0] != NULL)+ JUMPHERE(jump[0]);+#endif+ return cc + 32 / sizeof(PCRE2_UCHAR);++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ case OP_XCLASS:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+ compile_xclass_matchingpath(common, cc + LINK_SIZE, backtracks);+ return cc + GET(cc, 0) - 1;+#endif+ }+SLJIT_UNREACHABLE();+return cc;+}++static SLJIT_INLINE PCRE2_SPTR compile_charn_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, jump_list **backtracks)+{+/* This function consumes at least one input character. */+/* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */+DEFINE_COMPILER;+PCRE2_SPTR ccbegin = cc;+compare_context context;+int size;++context.length = 0;+do+ {+ if (cc >= ccend)+ break;++ if (*cc == OP_CHAR)+ {+ size = 1;+#ifdef SUPPORT_UNICODE+ if (common->utf && HAS_EXTRALEN(cc[1]))+ size += GET_EXTRALEN(cc[1]);+#endif+ }+ else if (*cc == OP_CHARI)+ {+ size = 1;+#ifdef SUPPORT_UNICODE+ if (common->utf)+ {+ if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)+ size = 0;+ else if (HAS_EXTRALEN(cc[1]))+ size += GET_EXTRALEN(cc[1]);+ }+ else+#endif+ if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)+ size = 0;+ }+ else+ size = 0;++ cc += 1 + size;+ context.length += IN_UCHARS(size);+ }+while (size > 0 && context.length <= 128);++cc = ccbegin;+if (context.length > 0)+ {+ /* We have a fixed-length byte sequence. */+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));++ context.sourcereg = -1;+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED+ context.ucharptr = 0;+#endif+ do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0);+ return cc;+ }++/* A non-fixed length character will be checked if length == 0. */+return compile_char1_matchingpath(common, *cc, cc + 1, backtracks, TRUE);+}++/* Forward definitions. */+static void compile_matchingpath(compiler_common *, PCRE2_SPTR, PCRE2_SPTR, backtrack_common *);+static void compile_backtrackingpath(compiler_common *, struct backtrack_common *);++#define PUSH_BACKTRACK(size, ccstart, error) \+ do \+ { \+ backtrack = sljit_alloc_memory(compiler, (size)); \+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \+ return error; \+ memset(backtrack, 0, size); \+ backtrack->prev = parent->top; \+ backtrack->cc = (ccstart); \+ parent->top = backtrack; \+ } \+ while (0)++#define PUSH_BACKTRACK_NOVALUE(size, ccstart) \+ do \+ { \+ backtrack = sljit_alloc_memory(compiler, (size)); \+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \+ return; \+ memset(backtrack, 0, size); \+ backtrack->prev = parent->top; \+ backtrack->cc = (ccstart); \+ parent->top = backtrack; \+ } \+ while (0)++#define BACKTRACK_AS(type) ((type *)backtrack)++static void compile_dnref_search(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)+{+/* The OVECTOR offset goes to TMP2. */+DEFINE_COMPILER;+int count = GET2(cc, 1 + IMM2_SIZE);+PCRE2_SPTR slot = common->name_table + GET2(cc, 1) * common->name_entry_size;+unsigned int offset;+jump_list *found = NULL;++SLJIT_ASSERT(*cc == OP_DNREF || *cc == OP_DNREFI);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));++count--;+while (count-- > 0)+ {+ offset = GET2(slot, 0) << 1;+ GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));+ add_jump(compiler, &found, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0));+ slot += common->name_entry_size;+ }++offset = GET2(slot, 0) << 1;+GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));+if (backtracks != NULL && !common->unset_backref)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0));++set_jumps(found, LABEL());+}++static void compile_ref_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)+{+DEFINE_COMPILER;+BOOL ref = (*cc == OP_REF || *cc == OP_REFI);+int offset = 0;+struct sljit_jump *jump = NULL;+struct sljit_jump *partial;+struct sljit_jump *nopartial;+#if defined SUPPORT_UNICODE+struct sljit_label *loop;+struct sljit_label *caseless_loop;+jump_list *no_match = NULL;+int source_reg = COUNT_MATCH;+int source_end_reg = ARGUMENTS;+int char1_reg = STACK_LIMIT;+#endif /* SUPPORT_UNICODE */++if (ref)+ {+ offset = GET2(cc, 1) << 1;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+ /* OVECTOR(1) contains the "string begin - 1" constant. */+ if (withchecks && !common->unset_backref)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));+ }+else+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);++#if defined SUPPORT_UNICODE+if (common->utf && *cc == OP_REFI)+ {+ SLJIT_ASSERT(common->iref_ptr != 0);++ if (ref)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ else+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));++ if (withchecks && emptyfail)+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, TMP2, 0));++ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr, source_reg, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw), source_end_reg, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2, char1_reg, 0);++ OP1(SLJIT_MOV, source_reg, 0, TMP1, 0);+ OP1(SLJIT_MOV, source_end_reg, 0, TMP2, 0);++ loop = LABEL();+ jump = CMP(SLJIT_GREATER_EQUAL, source_reg, 0, source_end_reg, 0);+ partial = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);++ /* Read original character. It must be a valid UTF character. */+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, source_reg, 0);++ read_char(common, 0, READ_CHAR_MAX, NULL, READ_CHAR_UPDATE_STR_PTR | READ_CHAR_VALID_UTF);++ OP1(SLJIT_MOV, source_reg, 0, STR_PTR, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+ OP1(SLJIT_MOV, char1_reg, 0, TMP1, 0);++ /* Read second character. */+ read_char(common, 0, READ_CHAR_MAX, &no_match, READ_CHAR_UPDATE_STR_PTR);++ CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);++ OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);++ add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));++ OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);++ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records));++ OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(ucd_record, other_case));+ OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(ucd_record, caseset));+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);+ CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);++ add_jump(compiler, &no_match, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0));+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_caseless_sets));++ caseless_loop = LABEL();+ OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP2), 0);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(uint32_t));+ OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, char1_reg, 0);+ JUMPTO(SLJIT_EQUAL, loop);+ JUMPTO(SLJIT_LESS, caseless_loop);++ set_jumps(no_match, LABEL());+ if (common->mode == PCRE2_JIT_COMPLETE)+ JUMPHERE(partial);++ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));++ if (common->mode != PCRE2_JIT_COMPLETE)+ {+ JUMPHERE(partial);+ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);++ check_partial(common, FALSE);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ }++ JUMPHERE(jump);+ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);+ return;+ }+else+#endif /* SUPPORT_UNICODE */+ {+ if (ref)+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);+ else+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);++ if (withchecks)+ jump = JUMP(SLJIT_ZERO);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+ partial = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);+ if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, backtracks, partial);++ add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));++ if (common->mode != PCRE2_JIT_COMPLETE)+ {+ nopartial = JUMP(SLJIT_JUMP);+ JUMPHERE(partial);+ /* TMP2 -= STR_END - STR_PTR */+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0);+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0);+ partial = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);+ add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));+ JUMPHERE(partial);+ check_partial(common, FALSE);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ JUMPHERE(nopartial);+ }+ }++if (jump != NULL)+ {+ if (emptyfail)+ add_jump(compiler, backtracks, jump);+ else+ JUMPHERE(jump);+ }+}++static SLJIT_INLINE PCRE2_SPTR compile_ref_iterator_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+BOOL ref = (*cc == OP_REF || *cc == OP_REFI);+backtrack_common *backtrack;+PCRE2_UCHAR type;+int offset = 0;+struct sljit_label *label;+struct sljit_jump *zerolength;+struct sljit_jump *jump = NULL;+PCRE2_SPTR ccbegin = cc;+int min = 0, max = 0;+BOOL minimize;++PUSH_BACKTRACK(sizeof(ref_iterator_backtrack), cc, NULL);++if (ref)+ offset = GET2(cc, 1) << 1;+else+ cc += IMM2_SIZE;+type = cc[1 + IMM2_SIZE];++SLJIT_COMPILE_ASSERT((OP_CRSTAR & 0x1) == 0, crstar_opcode_must_be_even);+minimize = (type & 0x1) != 0;+switch(type)+ {+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ min = 0;+ max = 0;+ cc += 1 + IMM2_SIZE + 1;+ break;+ case OP_CRPLUS:+ case OP_CRMINPLUS:+ min = 1;+ max = 0;+ cc += 1 + IMM2_SIZE + 1;+ break;+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ min = 0;+ max = 1;+ cc += 1 + IMM2_SIZE + 1;+ break;+ case OP_CRRANGE:+ case OP_CRMINRANGE:+ min = GET2(cc, 1 + IMM2_SIZE + 1);+ max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE);+ cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE;+ break;+ default:+ SLJIT_UNREACHABLE();+ break;+ }++if (!minimize)+ {+ if (min == 0)+ {+ allocate_stack(common, 2);+ if (ref)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);+ /* Temporary release of STR_PTR. */+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));+ /* Handles both invalid and empty cases. Since the minimum repeat,+ is zero the invalid case is basically the same as an empty case. */+ if (ref)+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ else+ {+ compile_dnref_search(common, ccbegin, NULL);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0);+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ }+ /* Restore if not zero length. */+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));+ }+ else+ {+ allocate_stack(common, 1);+ if (ref)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ if (ref)+ {+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ }+ else+ {+ compile_dnref_search(common, ccbegin, &backtrack->topbacktracks);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0);+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ }+ }++ if (min > 1 || max > 1)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, 0);++ label = LABEL();+ if (!ref)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);+ compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE);++ if (min > 1 || max > 1)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0);+ if (min > 1)+ CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, label);+ if (max > 1)+ {+ jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, label);+ JUMPHERE(jump);+ }+ }++ if (max == 0)+ {+ /* Includes min > 1 case as well. */+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, label);+ }++ JUMPHERE(zerolength);+ BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();++ count_match(common);+ return cc;+ }++allocate_stack(common, ref ? 2 : 3);+if (ref)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+if (type != OP_CRMINSTAR)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);++if (min == 0)+ {+ /* Handles both invalid and empty cases. Since the minimum repeat,+ is zero the invalid case is basically the same as an empty case. */+ if (ref)+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ else+ {+ compile_dnref_search(common, ccbegin, NULL);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ }+ /* Length is non-zero, we can match real repeats. */+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ jump = JUMP(SLJIT_JUMP);+ }+else+ {+ if (ref)+ {+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ }+ else+ {+ compile_dnref_search(common, ccbegin, &backtrack->topbacktracks);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);+ zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ }+ }++BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL();+if (max > 0)+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));++if (!ref)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));+compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE);+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);++if (min > 1)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);+ CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(ref_iterator_backtrack)->matchingpath);+ }+else if (max > 0)+ OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);++if (jump != NULL)+ JUMPHERE(jump);+JUMPHERE(zerolength);++count_match(common);+return cc;+}++static SLJIT_INLINE PCRE2_SPTR compile_recurse_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+recurse_entry *entry = common->entries;+recurse_entry *prev = NULL;+sljit_sw start = GET(cc, 1);+PCRE2_SPTR start_cc;+BOOL needs_control_head;++PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL);++/* Inlining simple patterns. */+if (get_framesize(common, common->start + start, NULL, TRUE, &needs_control_head) == no_stack)+ {+ start_cc = common->start + start;+ compile_matchingpath(common, next_opcode(common, start_cc), bracketend(start_cc) - (1 + LINK_SIZE), backtrack);+ BACKTRACK_AS(recurse_backtrack)->inlined_pattern = TRUE;+ return cc + 1 + LINK_SIZE;+ }++while (entry != NULL)+ {+ if (entry->start == start)+ break;+ prev = entry;+ entry = entry->next;+ }++if (entry == NULL)+ {+ entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;+ entry->next = NULL;+ entry->entry_label = NULL;+ entry->backtrack_label = NULL;+ entry->entry_calls = NULL;+ entry->backtrack_calls = NULL;+ entry->start = start;++ if (prev != NULL)+ prev->next = entry;+ else+ common->entries = entry;+ }++BACKTRACK_AS(recurse_backtrack)->entry = entry;++if (entry->entry_label == NULL)+ add_jump(compiler, &entry->entry_calls, JUMP(SLJIT_FAST_CALL));+else+ JUMPTO(SLJIT_FAST_CALL, entry->entry_label);+/* Leave if the match is failed. */+add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));+BACKTRACK_AS(recurse_backtrack)->matchingpath = LABEL();+return cc + 1 + LINK_SIZE;+}++static sljit_s32 SLJIT_FUNC do_callout(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector)+{+PCRE2_SPTR begin;+PCRE2_SIZE *ovector;+sljit_u32 oveccount, capture_top;++if (arguments->callout == NULL)+ return 0;++SLJIT_COMPILE_ASSERT(sizeof (PCRE2_SIZE) <= sizeof (sljit_sw), pcre2_size_must_be_lower_than_sljit_sw_size);++begin = arguments->begin;+ovector = (PCRE2_SIZE*)(callout_block + 1);+oveccount = callout_block->capture_top;++SLJIT_ASSERT(oveccount >= 1);++callout_block->version = 2;+callout_block->callout_flags = 0;++/* Offsets in subject. */+callout_block->subject_length = arguments->end - arguments->begin;+callout_block->start_match = jit_ovector[0] - begin;+callout_block->current_position = (PCRE2_SPTR)callout_block->offset_vector - begin;+callout_block->subject = begin;++/* Convert and copy the JIT offset vector to the ovector array. */+callout_block->capture_top = 1;+callout_block->offset_vector = ovector;++ovector[0] = PCRE2_UNSET;+ovector[1] = PCRE2_UNSET;+ovector += 2;+jit_ovector += 2;+capture_top = 1;++/* Convert pointers to sizes. */+while (--oveccount != 0)+ {+ capture_top++;++ ovector[0] = (PCRE2_SIZE)(jit_ovector[0] - begin);+ ovector[1] = (PCRE2_SIZE)(jit_ovector[1] - begin);++ if (ovector[0] != PCRE2_UNSET)+ callout_block->capture_top = capture_top;++ ovector += 2;+ jit_ovector += 2;+ }++return (arguments->callout)(callout_block, arguments->callout_data);+}++#define CALLOUT_ARG_OFFSET(arg) \+ SLJIT_OFFSETOF(pcre2_callout_block, arg)++static SLJIT_INLINE PCRE2_SPTR compile_callout_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+sljit_s32 mov_opcode;+unsigned int callout_length = (*cc == OP_CALLOUT)+ ? PRIV(OP_lengths)[OP_CALLOUT] : GET(cc, 1 + 2 * LINK_SIZE);+sljit_sw value1;+sljit_sw value2;+sljit_sw value3;+sljit_uw callout_arg_size = (common->re->top_bracket + 1) * 2 * sizeof(sljit_sw);++PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);++callout_arg_size = (sizeof(pcre2_callout_block) + callout_arg_size + sizeof(sljit_sw) - 1) / sizeof(sljit_sw);++allocate_stack(common, callout_arg_size);++SLJIT_ASSERT(common->capture_last_ptr != 0);+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);+OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+value1 = (*cc == OP_CALLOUT) ? cc[1 + 2 * LINK_SIZE] : 0;+OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, value1);+OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0);+OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_top), SLJIT_IMM, common->re->top_bracket + 1);++/* These pointer sized fields temporarly stores internal variables. */+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(offset_vector), STR_PTR, 0);++if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr));+mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 1));+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 1 + LINK_SIZE));++if (*cc == OP_CALLOUT)+ {+ value1 = 0;+ value2 = 0;+ value3 = 0;+ }+else+ {+ value1 = (sljit_sw) (cc + (1 + 4*LINK_SIZE) + 1);+ value2 = (callout_length - (1 + 4*LINK_SIZE + 2));+ value3 = (sljit_sw) (GET(cc, 1 + 3*LINK_SIZE));+ }++OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string), SLJIT_IMM, value1);+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_length), SLJIT_IMM, value2);+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_offset), SLJIT_IMM, value3);+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0);++SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);++/* Needed to save important temporary registers. */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);+/* SLJIT_R0 = arguments */+OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0);+GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START);+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(S32) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout));+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+free_stack(common, callout_arg_size);++/* Check return value. */+OP2(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER32));+if (common->abort_label == NULL)+ add_jump(compiler, &common->abort, JUMP(SLJIT_NOT_EQUAL32) /* SIG_LESS */);+else+ JUMPTO(SLJIT_NOT_EQUAL32 /* SIG_LESS */, common->abort_label);+return cc + callout_length;+}++#undef CALLOUT_ARG_SIZE+#undef CALLOUT_ARG_OFFSET++static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(PCRE2_SPTR cc)+{+while (TRUE)+ {+ switch (*cc)+ {+ case OP_CALLOUT_STR:+ cc += GET(cc, 1 + 2*LINK_SIZE);+ break;++ case OP_NOT_WORD_BOUNDARY:+ case OP_WORD_BOUNDARY:+ case OP_CIRC:+ case OP_CIRCM:+ case OP_DOLL:+ case OP_DOLLM:+ case OP_CALLOUT:+ case OP_ALT:+ cc += PRIV(OP_lengths)[*cc];+ break;++ case OP_KET:+ return FALSE;++ default:+ return TRUE;+ }+ }+}++static PCRE2_SPTR compile_assert_matchingpath(compiler_common *common, PCRE2_SPTR cc, assert_backtrack *backtrack, BOOL conditional)+{+DEFINE_COMPILER;+int framesize;+int extrasize;+BOOL local_quit_available = FALSE;+BOOL needs_control_head;+int private_data_ptr;+backtrack_common altbacktrack;+PCRE2_SPTR ccbegin;+PCRE2_UCHAR opcode;+PCRE2_UCHAR bra = OP_BRA;+jump_list *tmp = NULL;+jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;+jump_list **found;+/* Saving previous accept variables. */+BOOL save_local_quit_available = common->local_quit_available;+BOOL save_in_positive_assertion = common->in_positive_assertion;+then_trap_backtrack *save_then_trap = common->then_trap;+struct sljit_label *save_quit_label = common->quit_label;+struct sljit_label *save_accept_label = common->accept_label;+jump_list *save_quit = common->quit;+jump_list *save_positive_assertion_quit = common->positive_assertion_quit;+jump_list *save_accept = common->accept;+struct sljit_jump *jump;+struct sljit_jump *brajump = NULL;++/* Assert captures then. */+common->then_trap = NULL;++if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)+ {+ SLJIT_ASSERT(!conditional);+ bra = *cc;+ cc++;+ }+private_data_ptr = PRIVATE_DATA(cc);+SLJIT_ASSERT(private_data_ptr != 0);+framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head);+backtrack->framesize = framesize;+backtrack->private_data_ptr = private_data_ptr;+opcode = *cc;+SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);+found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;+ccbegin = cc;+cc += GET(cc, 1);++if (bra == OP_BRAMINZERO)+ {+ /* This is a braminzero backtrack path. */+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ }++if (framesize < 0)+ {+ extrasize = 1;+ if (bra == OP_BRA && !assert_needs_str_ptr_saving(ccbegin + 1 + LINK_SIZE))+ extrasize = 0;++ if (needs_control_head)+ extrasize++;++ if (framesize == no_frame)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);++ if (extrasize > 0)+ allocate_stack(common, extrasize);++ if (needs_control_head)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);++ if (extrasize > 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);++ if (needs_control_head)+ {+ SLJIT_ASSERT(extrasize == 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);+ }+ }+else+ {+ extrasize = needs_control_head ? 3 : 2;+ allocate_stack(common, framesize + extrasize);++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);+ if (needs_control_head)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);++ if (needs_control_head)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);+ }+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);++ init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize);+ }++memset(&altbacktrack, 0, sizeof(backtrack_common));+if (conditional || (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT))+ {+ /* Control verbs cannot escape from these asserts. */+ local_quit_available = TRUE;+ common->local_quit_available = TRUE;+ common->quit_label = NULL;+ common->quit = NULL;+ }++common->in_positive_assertion = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK);+common->positive_assertion_quit = NULL;++while (1)+ {+ common->accept_label = NULL;+ common->accept = NULL;+ altbacktrack.top = NULL;+ altbacktrack.topbacktracks = NULL;++ if (*ccbegin == OP_ALT && extrasize > 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));++ altbacktrack.cc = ccbegin;+ compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ {+ if (local_quit_available)+ {+ common->local_quit_available = save_local_quit_available;+ common->quit_label = save_quit_label;+ common->quit = save_quit;+ }+ common->in_positive_assertion = save_in_positive_assertion;+ common->then_trap = save_then_trap;+ common->accept_label = save_accept_label;+ common->positive_assertion_quit = save_positive_assertion_quit;+ common->accept = save_accept;+ return NULL;+ }+ common->accept_label = LABEL();+ if (common->accept != NULL)+ set_jumps(common->accept, common->accept_label);++ /* Reset stack. */+ if (framesize < 0)+ {+ if (framesize == no_frame)+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ else if (extrasize > 0)+ free_stack(common, extrasize);++ if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));+ }+ else+ {+ if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional)+ {+ /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));+ if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));+ }+ else+ {+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 2));+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw));+ }+ }++ if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)+ {+ /* We know that STR_PTR was stored on the top of the stack. */+ if (conditional)+ {+ if (extrasize > 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? STACK(-2) : STACK(-1));+ }+ else if (bra == OP_BRAZERO)+ {+ if (framesize < 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize));+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - extrasize));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else if (framesize >= 0)+ {+ /* For OP_BRA and OP_BRAMINZERO. */+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1));+ }+ }+ add_jump(compiler, found, JUMP(SLJIT_JUMP));++ compile_backtrackingpath(common, altbacktrack.top);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ {+ if (local_quit_available)+ {+ common->local_quit_available = save_local_quit_available;+ common->quit_label = save_quit_label;+ common->quit = save_quit;+ }+ common->in_positive_assertion = save_in_positive_assertion;+ common->then_trap = save_then_trap;+ common->accept_label = save_accept_label;+ common->positive_assertion_quit = save_positive_assertion_quit;+ common->accept = save_accept;+ return NULL;+ }+ set_jumps(altbacktrack.topbacktracks, LABEL());++ if (*cc != OP_ALT)+ break;++ ccbegin = cc;+ cc += GET(cc, 1);+ }++if (local_quit_available)+ {+ SLJIT_ASSERT(common->positive_assertion_quit == NULL);+ /* Makes the check less complicated below. */+ common->positive_assertion_quit = common->quit;+ }++/* None of them matched. */+if (common->positive_assertion_quit != NULL)+ {+ jump = JUMP(SLJIT_JUMP);+ set_jumps(common->positive_assertion_quit, LABEL());+ SLJIT_ASSERT(framesize != no_stack);+ if (framesize < 0)+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));+ else+ {+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (extrasize + 1) * sizeof(sljit_sw));+ }+ JUMPHERE(jump);+ }++if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(1));++if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)+ {+ /* Assert is failed. */+ if ((conditional && extrasize > 0) || bra == OP_BRAZERO)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));++ if (framesize < 0)+ {+ /* The topmost item should be 0. */+ if (bra == OP_BRAZERO)+ {+ if (extrasize == 2)+ free_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else if (extrasize > 0)+ free_stack(common, extrasize);+ }+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1));+ /* The topmost item should be 0. */+ if (bra == OP_BRAZERO)+ {+ free_stack(common, framesize + extrasize - 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else+ free_stack(common, framesize + extrasize);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }+ jump = JUMP(SLJIT_JUMP);+ if (bra != OP_BRAZERO)+ add_jump(compiler, target, jump);++ /* Assert is successful. */+ set_jumps(tmp, LABEL());+ if (framesize < 0)+ {+ /* We know that STR_PTR was stored on the top of the stack. */+ if (extrasize > 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize));++ /* Keep the STR_PTR on the top of the stack. */+ if (bra == OP_BRAZERO)+ {+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));+ if (extrasize == 2)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ }+ else if (bra == OP_BRAMINZERO)+ {+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ }+ else+ {+ if (bra == OP_BRA)+ {+ /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize + 1));+ }+ else+ {+ /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw));+ if (extrasize == 2)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ if (bra == OP_BRAMINZERO)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else+ {+ SLJIT_ASSERT(extrasize == 3);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0);+ }+ }+ }++ if (bra == OP_BRAZERO)+ {+ backtrack->matchingpath = LABEL();+ SET_LABEL(jump, backtrack->matchingpath);+ }+ else if (bra == OP_BRAMINZERO)+ {+ JUMPTO(SLJIT_JUMP, backtrack->matchingpath);+ JUMPHERE(brajump);+ if (framesize >= 0)+ {+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }+ set_jumps(backtrack->common.topbacktracks, LABEL());+ }+ }+else+ {+ /* AssertNot is successful. */+ if (framesize < 0)+ {+ if (extrasize > 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));++ if (bra != OP_BRA)+ {+ if (extrasize == 2)+ free_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else if (extrasize > 0)+ free_stack(common, extrasize);+ }+ else+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1));+ /* The topmost item should be 0. */+ if (bra != OP_BRA)+ {+ free_stack(common, framesize + extrasize - 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else+ free_stack(common, framesize + extrasize);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }++ if (bra == OP_BRAZERO)+ backtrack->matchingpath = LABEL();+ else if (bra == OP_BRAMINZERO)+ {+ JUMPTO(SLJIT_JUMP, backtrack->matchingpath);+ JUMPHERE(brajump);+ }++ if (bra != OP_BRA)+ {+ SLJIT_ASSERT(found == &backtrack->common.topbacktracks);+ set_jumps(backtrack->common.topbacktracks, LABEL());+ backtrack->common.topbacktracks = NULL;+ }+ }++if (local_quit_available)+ {+ common->local_quit_available = save_local_quit_available;+ common->quit_label = save_quit_label;+ common->quit = save_quit;+ }+common->in_positive_assertion = save_in_positive_assertion;+common->then_trap = save_then_trap;+common->accept_label = save_accept_label;+common->positive_assertion_quit = save_positive_assertion_quit;+common->accept = save_accept;+return cc + 1 + LINK_SIZE;+}++static SLJIT_INLINE void match_once_common(compiler_common *common, PCRE2_UCHAR ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head)+{+DEFINE_COMPILER;+int stacksize;++if (framesize < 0)+ {+ if (framesize == no_frame)+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ else+ {+ stacksize = needs_control_head ? 1 : 0;+ if (ket != OP_KET || has_alternatives)+ stacksize++;++ if (stacksize > 0)+ free_stack(common, stacksize);+ }++ if (needs_control_head)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? STACK(-2) : STACK(-1));++ /* TMP2 which is set here used by OP_KETRMAX below. */+ if (ket == OP_KETRMAX)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));+ else if (ket == OP_KETRMIN)+ {+ /* Move the STR_PTR to the private_data_ptr. */+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1));+ }+ }+else+ {+ stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1;+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw));+ if (needs_control_head)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-1));++ if (ket == OP_KETRMAX)+ {+ /* TMP2 which is set here used by OP_KETRMAX below. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ }+ }+if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0);+}++static SLJIT_INLINE int match_capture_common(compiler_common *common, int stacksize, int offset, int private_data_ptr)+{+DEFINE_COMPILER;++if (common->capture_last_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);+ stacksize++;+ }+if (common->optimized_cbracket[offset >> 1] == 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ stacksize += 2;+ }+return stacksize;+}++static PCRE2_SPTR SLJIT_FUNC do_script_run(PCRE2_SPTR ptr, PCRE2_SPTR endptr)+{+ if (PRIV(script_run)(ptr, endptr, FALSE))+ return endptr;+ return NULL;+}++#ifdef SUPPORT_UNICODE++static PCRE2_SPTR SLJIT_FUNC do_script_run_utf(PCRE2_SPTR ptr, PCRE2_SPTR endptr)+{+ if (PRIV(script_run)(ptr, endptr, TRUE))+ return endptr;+ return NULL;+}++#endif /* SUPPORT_UNICODE */++static SLJIT_INLINE void match_script_run_common(compiler_common *common, int private_data_ptr, backtrack_common *parent)+{+DEFINE_COMPILER;++SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+#ifdef SUPPORT_UNICODE+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,+ common->utf ? SLJIT_FUNC_OFFSET(do_script_run_utf) : SLJIT_FUNC_OFFSET(do_script_run));+#else+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_script_run));+#endif++OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);+add_jump(compiler, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));+}++/*+ Handling bracketed expressions is probably the most complex part.++ Stack layout naming characters:+ S - Push the current STR_PTR+ 0 - Push a 0 (NULL)+ A - Push the current STR_PTR. Needed for restoring the STR_PTR+ before the next alternative. Not pushed if there are no alternatives.+ M - Any values pushed by the current alternative. Can be empty, or anything.+ C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.+ L - Push the previous local (pointed by localptr) to the stack+ () - opional values stored on the stack+ ()* - optonal, can be stored multiple times++ The following list shows the regular expression templates, their PCRE byte codes+ and stack layout supported by pcre-sljit.++ (?:) OP_BRA | OP_KET A M+ () OP_CBRA | OP_KET C M+ (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*+ OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*+ (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*+ OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*+ ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*+ OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*+ ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*+ OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*+ (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )+ (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )+ ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )+ ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )+ (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*+ OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*+ (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*+ OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*+ ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*+ OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*+ ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*+ OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*+++ Stack layout naming characters:+ A - Push the alternative index (starting from 0) on the stack.+ Not pushed if there is no alternatives.+ M - Any values pushed by the current alternative. Can be empty, or anything.++ The next list shows the possible content of a bracket:+ (|) OP_*BRA | OP_ALT ... M A+ (?()|) OP_*COND | OP_ALT M A+ (?>|) OP_ONCE | OP_ALT ... [stack trace] M A+ Or nothing, if trace is unnecessary+*/++static PCRE2_SPTR compile_bracket_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+PCRE2_UCHAR opcode;+int private_data_ptr = 0;+int offset = 0;+int i, stacksize;+int repeat_ptr = 0, repeat_length = 0;+int repeat_type = 0, repeat_count = 0;+PCRE2_SPTR ccbegin;+PCRE2_SPTR matchingpath;+PCRE2_SPTR slot;+PCRE2_UCHAR bra = OP_BRA;+PCRE2_UCHAR ket;+assert_backtrack *assert;+BOOL has_alternatives;+BOOL needs_control_head = FALSE;+struct sljit_jump *jump;+struct sljit_jump *skip;+struct sljit_label *rmax_label = NULL;+struct sljit_jump *braminzero = NULL;++PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);++if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)+ {+ bra = *cc;+ cc++;+ opcode = *cc;+ }++opcode = *cc;+ccbegin = cc;+matchingpath = bracketend(cc) - 1 - LINK_SIZE;+ket = *matchingpath;+if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0)+ {+ repeat_ptr = PRIVATE_DATA(matchingpath);+ repeat_length = PRIVATE_DATA(matchingpath + 1);+ repeat_type = PRIVATE_DATA(matchingpath + 2);+ repeat_count = PRIVATE_DATA(matchingpath + 3);+ SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0);+ if (repeat_type == OP_UPTO)+ ket = OP_KETRMAX;+ if (repeat_type == OP_MINUPTO)+ ket = OP_KETRMIN;+ }++matchingpath = ccbegin + 1 + LINK_SIZE;+SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);+SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));+cc += GET(cc, 1);++has_alternatives = *cc == OP_ALT;+if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND))+ {+ SLJIT_COMPILE_ASSERT(OP_DNRREF == OP_RREF + 1 && OP_FALSE == OP_RREF + 2 && OP_TRUE == OP_RREF + 3,+ compile_time_checks_must_be_grouped_together);+ has_alternatives = ((*matchingpath >= OP_RREF && *matchingpath <= OP_TRUE) || *matchingpath == OP_FAIL) ? FALSE : TRUE;+ }++if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))+ opcode = OP_SCOND;++if (opcode == OP_CBRA || opcode == OP_SCBRA)+ {+ /* Capturing brackets has a pre-allocated space. */+ offset = GET2(ccbegin, 1 + LINK_SIZE);+ if (common->optimized_cbracket[offset] == 0)+ {+ private_data_ptr = OVECTOR_PRIV(offset);+ offset <<= 1;+ }+ else+ {+ offset <<= 1;+ private_data_ptr = OVECTOR(offset);+ }+ BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;+ matchingpath += IMM2_SIZE;+ }+else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_ONCE || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)+ {+ /* Other brackets simply allocate the next entry. */+ private_data_ptr = PRIVATE_DATA(ccbegin);+ SLJIT_ASSERT(private_data_ptr != 0);+ BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;+ if (opcode == OP_ONCE)+ BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, NULL, FALSE, &needs_control_head);+ }++/* Instructions before the first alternative. */+stacksize = 0;+if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))+ stacksize++;+if (bra == OP_BRAZERO)+ stacksize++;++if (stacksize > 0)+ allocate_stack(common, stacksize);++stacksize = 0;+if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);+ stacksize++;+ }++if (bra == OP_BRAZERO)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);++if (bra == OP_BRAMINZERO)+ {+ /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ if (ket != OP_KETRMIN)+ {+ free_stack(common, 1);+ braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ }+ else if (opcode == OP_ONCE || opcode >= OP_SBRA)+ {+ jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ /* Nothing stored during the first run. */+ skip = JUMP(SLJIT_JUMP);+ JUMPHERE(jump);+ /* Checking zero-length iteration. */+ if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)+ {+ /* When we come from outside, private_data_ptr contains the previous STR_PTR. */+ braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ }+ else+ {+ /* Except when the whole stack frame must be saved. */+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-BACKTRACK_AS(bracket_backtrack)->u.framesize - 2));+ }+ JUMPHERE(skip);+ }+ else+ {+ jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ JUMPHERE(jump);+ }+ }++if (repeat_type != 0)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, repeat_count);+ if (repeat_type == OP_EXACT)+ rmax_label = LABEL();+ }++if (ket == OP_KETRMIN)+ BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();++if (ket == OP_KETRMAX)+ {+ rmax_label = LABEL();+ if (has_alternatives && opcode >= OP_BRA && opcode < OP_SBRA && repeat_type == 0)+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmax_label;+ }++/* Handling capturing brackets and alternatives. */+if (opcode == OP_ONCE)+ {+ stacksize = 0;+ if (needs_control_head)+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ stacksize++;+ }++ if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)+ {+ /* Neither capturing brackets nor recursions are found in the block. */+ if (ket == OP_KETRMIN)+ {+ stacksize += 2;+ if (!needs_control_head)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ }+ else+ {+ if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);+ if (ket == OP_KETRMAX || has_alternatives)+ stacksize++;+ }++ if (stacksize > 0)+ allocate_stack(common, stacksize);++ stacksize = 0;+ if (needs_control_head)+ {+ stacksize++;+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);+ }++ if (ket == OP_KETRMIN)+ {+ if (needs_control_head)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);+ if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame)+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0);+ }+ else if (ket == OP_KETRMAX || has_alternatives)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);+ }+ else+ {+ if (ket != OP_KET || has_alternatives)+ stacksize++;++ stacksize += BACKTRACK_AS(bracket_backtrack)->u.framesize + 1;+ allocate_stack(common, stacksize);++ if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));++ stacksize = needs_control_head ? 1 : 0;+ if (ket != OP_KET || has_alternatives)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);+ stacksize++;+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);+ }+ else+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);+ }+ init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1);+ }+ }+else if (opcode == OP_CBRA || opcode == OP_SCBRA)+ {+ /* Saving the previous values. */+ if (common->optimized_cbracket[offset >> 1] != 0)+ {+ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset));+ allocate_stack(common, 2);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);+ }+ }+else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)+ {+ /* Saving the previous value. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);+ }+else if (has_alternatives)+ {+ /* Pushing the starting string pointer. */+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ }++/* Generating code for the first alternative. */+if (opcode == OP_COND || opcode == OP_SCOND)+ {+ if (*matchingpath == OP_CREF)+ {+ SLJIT_ASSERT(has_alternatives);+ add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed),+ CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));+ matchingpath += 1 + IMM2_SIZE;+ }+ else if (*matchingpath == OP_DNCREF)+ {+ SLJIT_ASSERT(has_alternatives);++ i = GET2(matchingpath, 1 + IMM2_SIZE);+ slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);+ slot += common->name_entry_size;+ i--;+ while (i-- > 0)+ {+ OP2(SLJIT_SUB, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);+ OP2(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, STR_PTR, 0);+ slot += common->name_entry_size;+ }+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+ add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_ZERO));+ matchingpath += 1 + 2 * IMM2_SIZE;+ }+ else if ((*matchingpath >= OP_RREF && *matchingpath <= OP_TRUE) || *matchingpath == OP_FAIL)+ {+ /* Never has other case. */+ BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;+ SLJIT_ASSERT(!has_alternatives);++ if (*matchingpath == OP_TRUE)+ {+ stacksize = 1;+ matchingpath++;+ }+ else if (*matchingpath == OP_FALSE || *matchingpath == OP_FAIL)+ stacksize = 0;+ else if (*matchingpath == OP_RREF)+ {+ stacksize = GET2(matchingpath, 1);+ if (common->currententry == NULL)+ stacksize = 0;+ else if (stacksize == RREF_ANY)+ stacksize = 1;+ else if (common->currententry->start == 0)+ stacksize = stacksize == 0;+ else+ stacksize = stacksize == (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);++ if (stacksize != 0)+ matchingpath += 1 + IMM2_SIZE;+ }+ else+ {+ if (common->currententry == NULL || common->currententry->start == 0)+ stacksize = 0;+ else+ {+ stacksize = GET2(matchingpath, 1 + IMM2_SIZE);+ slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;+ i = (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);+ while (stacksize > 0)+ {+ if ((int)GET2(slot, 0) == i)+ break;+ slot += common->name_entry_size;+ stacksize--;+ }+ }++ if (stacksize != 0)+ matchingpath += 1 + 2 * IMM2_SIZE;+ }++ /* The stacksize == 0 is a common "else" case. */+ if (stacksize == 0)+ {+ if (*cc == OP_ALT)+ {+ matchingpath = cc + 1 + LINK_SIZE;+ cc += GET(cc, 1);+ }+ else+ matchingpath = cc;+ }+ }+ else+ {+ SLJIT_ASSERT(has_alternatives && *matchingpath >= OP_ASSERT && *matchingpath <= OP_ASSERTBACK_NOT);+ /* Similar code as PUSH_BACKTRACK macro. */+ assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack));+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;+ memset(assert, 0, sizeof(assert_backtrack));+ assert->common.cc = matchingpath;+ BACKTRACK_AS(bracket_backtrack)->u.assert = assert;+ matchingpath = compile_assert_matchingpath(common, matchingpath, assert, TRUE);+ }+ }++compile_matchingpath(common, matchingpath, cc, backtrack);+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;++if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);++if (opcode == OP_ONCE)+ match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);++if (opcode == OP_SCRIPT_RUN)+ match_script_run_common(common, private_data_ptr, backtrack);++stacksize = 0;+if (repeat_type == OP_MINUPTO)+ {+ /* We need to preserve the counter. TMP2 will be used below. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);+ stacksize++;+ }+if (ket != OP_KET || bra != OP_BRA)+ stacksize++;+if (offset != 0)+ {+ if (common->capture_last_ptr != 0)+ stacksize++;+ if (common->optimized_cbracket[offset >> 1] == 0)+ stacksize += 2;+ }+if (has_alternatives && opcode != OP_ONCE)+ stacksize++;++if (stacksize > 0)+ allocate_stack(common, stacksize);++stacksize = 0;+if (repeat_type == OP_MINUPTO)+ {+ /* TMP2 was set above. */+ OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);+ stacksize++;+ }++if (ket != OP_KET || bra != OP_BRA)+ {+ if (ket != OP_KET)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);+ stacksize++;+ }++if (offset != 0)+ stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);++/* Skip and count the other alternatives. */+i = 1;+while (*cc == OP_ALT)+ {+ cc += GET(cc, 1);+ i++;+ }++if (has_alternatives)+ {+ if (opcode != OP_ONCE)+ {+ if (i <= 3)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);+ else+ BACKTRACK_AS(bracket_backtrack)->u.matching_put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));+ }+ if (ket != OP_KETRMAX)+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();+ }++/* Must be after the matchingpath label. */+if (offset != 0 && common->optimized_cbracket[offset >> 1] != 0)+ {+ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+ }++if (ket == OP_KETRMAX)+ {+ if (repeat_type != 0)+ {+ if (has_alternatives)+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, rmax_label);+ /* Drop STR_PTR for greedy plus quantifier. */+ if (opcode != OP_ONCE)+ free_stack(common, 1);+ }+ else if (opcode < OP_BRA || opcode >= OP_SBRA)+ {+ if (has_alternatives)+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();++ /* Checking zero-length iteration. */+ if (opcode != OP_ONCE)+ {+ /* This case includes opcodes such as OP_SCRIPT_RUN. */+ CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0, rmax_label);+ /* Drop STR_PTR for greedy plus quantifier. */+ if (bra != OP_BRAZERO)+ free_stack(common, 1);+ }+ else+ /* TMP2 must contain the starting STR_PTR. */+ CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label);+ }+ else+ JUMPTO(SLJIT_JUMP, rmax_label);+ BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();+ }++if (repeat_type == OP_EXACT)+ {+ count_match(common);+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, rmax_label);+ }+else if (repeat_type == OP_UPTO)+ {+ /* We need to preserve the counter. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);+ }++if (bra == OP_BRAZERO)+ BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();++if (bra == OP_BRAMINZERO)+ {+ /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */+ JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath);+ if (braminzero != NULL)+ {+ JUMPHERE(braminzero);+ /* We need to release the end pointer to perform the+ backtrack for the zero-length iteration. When+ framesize is < 0, OP_ONCE will do the release itself. */+ if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0)+ {+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (BACKTRACK_AS(bracket_backtrack)->u.framesize - 1) * sizeof(sljit_sw));+ }+ else if (ket == OP_KETRMIN && opcode != OP_ONCE)+ free_stack(common, 1);+ }+ /* Continue to the normal backtrack. */+ }++if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)+ count_match(common);++cc += 1 + LINK_SIZE;++if (opcode == OP_ONCE)+ {+ /* We temporarily encode the needs_control_head in the lowest bit.+ Note: on the target architectures of SLJIT the ((x << 1) >> 1) returns+ the same value for small signed numbers (including negative numbers). */+ BACKTRACK_AS(bracket_backtrack)->u.framesize = (int)((unsigned)BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);+ }+return cc + repeat_length;+}++static PCRE2_SPTR compile_bracketpos_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+PCRE2_UCHAR opcode;+int private_data_ptr;+int cbraprivptr = 0;+BOOL needs_control_head;+int framesize;+int stacksize;+int offset = 0;+BOOL zero = FALSE;+PCRE2_SPTR ccbegin = NULL;+int stack; /* Also contains the offset of control head. */+struct sljit_label *loop = NULL;+struct jump_list *emptymatch = NULL;++PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL);+if (*cc == OP_BRAPOSZERO)+ {+ zero = TRUE;+ cc++;+ }++opcode = *cc;+private_data_ptr = PRIVATE_DATA(cc);+SLJIT_ASSERT(private_data_ptr != 0);+BACKTRACK_AS(bracketpos_backtrack)->private_data_ptr = private_data_ptr;+switch(opcode)+ {+ case OP_BRAPOS:+ case OP_SBRAPOS:+ ccbegin = cc + 1 + LINK_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ offset = GET2(cc, 1 + LINK_SIZE);+ /* This case cannot be optimized in the same was as+ normal capturing brackets. */+ SLJIT_ASSERT(common->optimized_cbracket[offset] == 0);+ cbraprivptr = OVECTOR_PRIV(offset);+ offset <<= 1;+ ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE;+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head);+BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize;+if (framesize < 0)+ {+ if (offset != 0)+ {+ stacksize = 2;+ if (common->capture_last_ptr != 0)+ stacksize++;+ }+ else+ stacksize = 1;++ if (needs_control_head)+ stacksize++;+ if (!zero)+ stacksize++;++ BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;+ allocate_stack(common, stacksize);+ if (framesize == no_frame)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);++ stack = 0;+ if (offset != 0)+ {+ stack = 2;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);+ if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);+ if (needs_control_head)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ if (common->capture_last_ptr != 0)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);+ stack = 3;+ }+ }+ else+ {+ if (needs_control_head)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ stack = 1;+ }++ if (needs_control_head)+ stack++;+ if (!zero)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), SLJIT_IMM, 1);+ if (needs_control_head)+ {+ stack--;+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0);+ }+ }+else+ {+ stacksize = framesize + 1;+ if (!zero)+ stacksize++;+ if (needs_control_head)+ stacksize++;+ if (offset == 0)+ stacksize++;+ BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;++ allocate_stack(common, stacksize);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ if (needs_control_head)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));++ stack = 0;+ if (!zero)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);+ stack = 1;+ }+ if (needs_control_head)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0);+ stack++;+ }+ if (offset == 0)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0);+ stack++;+ }+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0);+ init_frame(common, cc, NULL, stacksize - 1, stacksize - framesize);+ stack -= 1 + (offset == 0);+ }++if (offset != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0);++loop = LABEL();+while (*cc != OP_KETRPOS)+ {+ backtrack->top = NULL;+ backtrack->topbacktracks = NULL;+ cc += GET(cc, 1);++ compile_matchingpath(common, ccbegin, cc, backtrack);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;++ if (framesize < 0)+ {+ if (framesize == no_frame)+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);++ if (offset != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0);+ if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ }+ else+ {+ if (opcode == OP_SBRAPOS)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ }++ /* Even if the match is empty, we need to reset the control head. */+ if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));++ if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)+ add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));++ if (!zero)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);+ }+ else+ {+ if (offset != 0)+ {+ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0);+ if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP2(SLJIT_SUB, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));+ if (opcode == OP_SBRAPOS)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2));+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(-framesize - 2), STR_PTR, 0);+ }++ /* Even if the match is empty, we need to reset the control head. */+ if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));++ if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)+ add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));++ if (!zero)+ {+ if (framesize < 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ }++ JUMPTO(SLJIT_JUMP, loop);+ flush_stubs(common);++ compile_backtrackingpath(common, backtrack->top);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;+ set_jumps(backtrack->topbacktracks, LABEL());++ if (framesize < 0)+ {+ if (offset != 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);+ else+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ }+ else+ {+ if (offset != 0)+ {+ /* Last alternative. */+ if (*cc == OP_KETRPOS)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr);+ }+ else+ {+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2));+ }+ }++ if (*cc == OP_KETRPOS)+ break;+ ccbegin = cc + 1 + LINK_SIZE;+ }++/* We don't have to restore the control head in case of a failed match. */++backtrack->topbacktracks = NULL;+if (!zero)+ {+ if (framesize < 0)+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));+ else /* TMP2 is set to [private_data_ptr] above. */+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), STACK(-stacksize), SLJIT_IMM, 0));+ }++/* None of them matched. */+set_jumps(emptymatch, LABEL());+count_match(common);+return cc + 1 + LINK_SIZE;+}++static SLJIT_INLINE PCRE2_SPTR get_iterator_parameters(compiler_common *common, PCRE2_SPTR cc, PCRE2_UCHAR *opcode, PCRE2_UCHAR *type, sljit_u32 *max, sljit_u32 *exact, PCRE2_SPTR *end)+{+int class_len;++*opcode = *cc;+*exact = 0;++if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO)+ {+ cc++;+ *type = OP_CHAR;+ }+else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI)+ {+ cc++;+ *type = OP_CHARI;+ *opcode -= OP_STARI - OP_STAR;+ }+else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO)+ {+ cc++;+ *type = OP_NOT;+ *opcode -= OP_NOTSTAR - OP_STAR;+ }+else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI)+ {+ cc++;+ *type = OP_NOTI;+ *opcode -= OP_NOTSTARI - OP_STAR;+ }+else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO)+ {+ cc++;+ *opcode -= OP_TYPESTAR - OP_STAR;+ *type = OP_END;+ }+else+ {+ SLJIT_ASSERT(*opcode == OP_CLASS || *opcode == OP_NCLASS || *opcode == OP_XCLASS);+ *type = *opcode;+ cc++;+ class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(PCRE2_UCHAR))) : GET(cc, 0);+ *opcode = cc[class_len - 1];++ if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)+ {+ *opcode -= OP_CRSTAR - OP_STAR;+ *end = cc + class_len;++ if (*opcode == OP_PLUS || *opcode == OP_MINPLUS)+ {+ *exact = 1;+ *opcode -= OP_PLUS - OP_STAR;+ }+ }+ else if (*opcode >= OP_CRPOSSTAR && *opcode <= OP_CRPOSQUERY)+ {+ *opcode -= OP_CRPOSSTAR - OP_POSSTAR;+ *end = cc + class_len;++ if (*opcode == OP_POSPLUS)+ {+ *exact = 1;+ *opcode = OP_POSSTAR;+ }+ }+ else+ {+ SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE || *opcode == OP_CRPOSRANGE);+ *max = GET2(cc, (class_len + IMM2_SIZE));+ *exact = GET2(cc, class_len);++ if (*max == 0)+ {+ if (*opcode == OP_CRPOSRANGE)+ *opcode = OP_POSSTAR;+ else+ *opcode -= OP_CRRANGE - OP_STAR;+ }+ else+ {+ *max -= *exact;+ if (*max == 0)+ *opcode = OP_EXACT;+ else if (*max == 1)+ {+ if (*opcode == OP_CRPOSRANGE)+ *opcode = OP_POSQUERY;+ else+ *opcode -= OP_CRRANGE - OP_QUERY;+ }+ else+ {+ if (*opcode == OP_CRPOSRANGE)+ *opcode = OP_POSUPTO;+ else+ *opcode -= OP_CRRANGE - OP_UPTO;+ }+ }+ *end = cc + class_len + 2 * IMM2_SIZE;+ }+ return cc;+ }++switch(*opcode)+ {+ case OP_EXACT:+ *exact = GET2(cc, 0);+ cc += IMM2_SIZE;+ break;++ case OP_PLUS:+ case OP_MINPLUS:+ *exact = 1;+ *opcode -= OP_PLUS - OP_STAR;+ break;++ case OP_POSPLUS:+ *exact = 1;+ *opcode = OP_POSSTAR;+ break;++ case OP_UPTO:+ case OP_MINUPTO:+ case OP_POSUPTO:+ *max = GET2(cc, 0);+ cc += IMM2_SIZE;+ break;+ }++if (*type == OP_END)+ {+ *type = *cc;+ *end = next_opcode(common, cc);+ cc++;+ return cc;+ }++*end = cc + 1;+#ifdef SUPPORT_UNICODE+if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);+#endif+return cc;+}++static PCRE2_SPTR compile_iterator_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+PCRE2_UCHAR opcode;+PCRE2_UCHAR type;+sljit_u32 max = 0, exact;+sljit_s32 early_fail_ptr = PRIVATE_DATA(cc + 1);+sljit_s32 early_fail_type;+BOOL charpos_enabled;+PCRE2_UCHAR charpos_char;+unsigned int charpos_othercasebit;+PCRE2_SPTR end;+jump_list *no_match = NULL;+jump_list *no_char1_match = NULL;+struct sljit_jump *jump = NULL;+struct sljit_label *label;+int private_data_ptr = PRIVATE_DATA(cc);+int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP);+int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr;+int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);+int tmp_base, tmp_offset;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+BOOL use_tmp;+#endif++PUSH_BACKTRACK(sizeof(char_iterator_backtrack), cc, NULL);++early_fail_type = (early_fail_ptr & 0x7);+early_fail_ptr >>= 3;++/* During recursion, these optimizations are disabled. */+if (common->early_fail_start_ptr == 0)+ {+ early_fail_ptr = 0;+ early_fail_type = type_skip;+ }++SLJIT_ASSERT(common->fast_forward_bc_ptr != NULL || early_fail_ptr == 0+ || (early_fail_ptr >= common->early_fail_start_ptr && early_fail_ptr <= common->early_fail_end_ptr));++if (early_fail_type == type_fail)+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr));++cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end);++if (type != OP_EXTUNI)+ {+ tmp_base = TMP3;+ tmp_offset = 0;+ }+else+ {+ tmp_base = SLJIT_MEM1(SLJIT_SP);+ tmp_offset = POSSESSIVE0;+ }++/* Handle fixed part first. */+if (exact > 1)+ {+ SLJIT_ASSERT(early_fail_ptr == 0);++ if (common->mode == PCRE2_JIT_COMPLETE+#ifdef SUPPORT_UNICODE+ && !common->utf+#endif+ && type != OP_ANYNL && type != OP_EXTUNI)+ {+ OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact));+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER, TMP1, 0, STR_END, 0));+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);+ }+ else+ {+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE);+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);+ }+ }+else if (exact == 1)+ {+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE);++ if (early_fail_type == type_fail_range)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + (int)sizeof(sljit_sw));+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, TMP2, 0);+ OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, TMP2, 0);+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, TMP2, 0, TMP1, 0));++ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + (int)sizeof(sljit_sw), STR_PTR, 0);+ }+ }++switch(opcode)+ {+ case OP_STAR:+ case OP_UPTO:+ SLJIT_ASSERT(early_fail_ptr == 0 || opcode == OP_STAR);++ if (type == OP_ANYNL || type == OP_EXTUNI)+ {+ SLJIT_ASSERT(private_data_ptr == 0);+ SLJIT_ASSERT(early_fail_ptr == 0);++ allocate_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);++ if (opcode == OP_UPTO)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, max);++ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE);+ if (opcode == OP_UPTO)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+ jump = JUMP(SLJIT_ZERO);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0);+ }++ /* We cannot use TMP3 because of allocate_stack. */+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, label);+ if (jump != NULL)+ JUMPHERE(jump);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;+ }+#ifdef SUPPORT_UNICODE+ else if (type == OP_ALLANY && !common->invalid_utf)+#else+ else if (type == OP_ALLANY)+#endif+ {+ if (opcode == OP_STAR)+ {+ if (private_data_ptr == 0)+ allocate_stack(common, 2);++ OP1(SLJIT_MOV, base, offset0, STR_END, 0);+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);++ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);+ process_partial_match(common);++ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_END, 0);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;+ }+#ifdef SUPPORT_UNICODE+ else if (!common->utf)+#else+ else+#endif+ {+ if (private_data_ptr == 0)+ allocate_stack(common, 2);++ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max));++ if (common->mode == PCRE2_JIT_COMPLETE)+ {+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);+ CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);+ }+ else+ {+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);+ process_partial_match(common);+ JUMPHERE(jump);+ }++ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);++ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;+ }+ }++ charpos_enabled = FALSE;+ charpos_char = 0;+ charpos_othercasebit = 0;++ if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI))+ {+#ifdef SUPPORT_UNICODE+ charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]);+#else+ charpos_enabled = TRUE;+#endif+ if (charpos_enabled && *end == OP_CHARI && char_has_othercase(common, end + 1))+ {+ charpos_othercasebit = char_get_othercase_bit(common, end + 1);+ if (charpos_othercasebit == 0)+ charpos_enabled = FALSE;+ }++ if (charpos_enabled)+ {+ charpos_char = end[1];+ /* Consume the OP_CHAR opcode. */+ end += 2;+#if PCRE2_CODE_UNIT_WIDTH == 8+ SLJIT_ASSERT((charpos_othercasebit >> 8) == 0);+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ SLJIT_ASSERT((charpos_othercasebit >> 9) == 0);+ if ((charpos_othercasebit & 0x100) != 0)+ charpos_othercasebit = (charpos_othercasebit & 0xff) << 8;+#endif+ if (charpos_othercasebit != 0)+ charpos_char |= charpos_othercasebit;++ BACKTRACK_AS(char_iterator_backtrack)->u.charpos.enabled = TRUE;+ BACKTRACK_AS(char_iterator_backtrack)->u.charpos.chr = charpos_char;+ BACKTRACK_AS(char_iterator_backtrack)->u.charpos.othercasebit = charpos_othercasebit;+ }+ }++ if (charpos_enabled)+ {+ if (opcode == OP_UPTO)+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max + 1);++ /* Search the first instance of charpos_char. */+ jump = JUMP(SLJIT_JUMP);+ label = LABEL();+ if (opcode == OP_UPTO)+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);+ add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO));+ }+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);+ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ JUMPHERE(jump);++ detect_partial_match(common, &backtrack->topbacktracks);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ if (charpos_othercasebit != 0)+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);++ if (private_data_ptr == 0)+ allocate_stack(common, 2);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);++ if (opcode == OP_UPTO)+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));+ }++ /* Search the last instance of charpos_char. */+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);+ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ detect_partial_match(common, &no_match);+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ if (charpos_othercasebit != 0)+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);++ if (opcode == OP_STAR)+ {+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, label);+ }+ else+ {+ jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ JUMPHERE(jump);+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);+ }++ set_jumps(no_match, LABEL());+ OP2(SLJIT_ADD, STR_PTR, 0, base, offset0, SLJIT_IMM, IN_UCHARS(1));+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ }+ else+ {+ if (private_data_ptr == 0)+ allocate_stack(common, 2);++ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ use_tmp = (!HAS_VIRTUAL_REGISTERS && opcode == OP_STAR);+ SLJIT_ASSERT(!use_tmp || tmp_base == TMP3);++ if (common->utf)+ OP1(SLJIT_MOV, use_tmp ? TMP3 : base, use_tmp ? 0 : offset0, STR_PTR, 0);+#endif+ if (opcode == OP_UPTO)+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);++ detect_partial_match(common, &no_match);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ OP1(SLJIT_MOV, use_tmp ? TMP3 : base, use_tmp ? 0 : offset0, STR_PTR, 0);+#endif++ if (opcode == OP_UPTO)+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));+ }++ detect_partial_match_to(common, label);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ set_jumps(no_char1_match, LABEL());+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ {+ set_jumps(no_match, LABEL());+ if (use_tmp)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+ OP1(SLJIT_MOV, base, offset0, TMP3, 0);+ }+ else+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ }+ else+#endif+ {+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ set_jumps(no_match, LABEL());+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ }++ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ }++ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;++ case OP_MINSTAR:+ if (private_data_ptr == 0)+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ break;++ case OP_MINUPTO:+ SLJIT_ASSERT(early_fail_ptr == 0);+ if (private_data_ptr == 0)+ allocate_stack(common, 2);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, max + 1);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;++ case OP_QUERY:+ case OP_MINQUERY:+ SLJIT_ASSERT(early_fail_ptr == 0);+ if (private_data_ptr == 0)+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ if (opcode == OP_QUERY)+ compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;++ case OP_EXACT:+ break;++ case OP_POSSTAR:+#if defined SUPPORT_UNICODE+ if (type == OP_ALLANY && !common->invalid_utf)+#else+ if (type == OP_ALLANY)+#endif+ {+ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);+ process_partial_match(common);+ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_END, 0);+ break;+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ {+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);+ detect_partial_match(common, &no_match);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);+ detect_partial_match_to(common, label);++ set_jumps(no_match, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);+ if (early_fail_ptr != 0)+ {+ if (!HAS_VIRTUAL_REGISTERS && tmp_base == TMP3)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, TMP3, 0);+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ }+ break;+ }+#endif++ detect_partial_match(common, &no_match);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);+ detect_partial_match_to(common, label);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ set_jumps(no_char1_match, LABEL());+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ set_jumps(no_match, LABEL());+ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ break;++ case OP_POSUPTO:+ SLJIT_ASSERT(early_fail_ptr == 0);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);++ detect_partial_match(common, &no_match);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));+ detect_partial_match_to(common, label);++ set_jumps(no_match, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);+ break;+ }+#endif++ if (type == OP_ALLANY)+ {+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max));++ if (common->mode == PCRE2_JIT_COMPLETE)+ {+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);+ CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);+ }+ else+ {+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);+ process_partial_match(common);+ JUMPHERE(jump);+ }+ break;+ }++ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);++ detect_partial_match(common, &no_match);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));+ detect_partial_match_to(common, label);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ set_jumps(no_char1_match, LABEL());+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ set_jumps(no_match, LABEL());+ break;++ case OP_POSQUERY:+ SLJIT_ASSERT(early_fail_ptr == 0);+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);+ compile_char1_matchingpath(common, type, cc, &no_match, TRUE);+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);+ set_jumps(no_match, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++count_match(common);+return end;+}++static SLJIT_INLINE PCRE2_SPTR compile_fail_accept_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;++PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);++if (*cc == OP_FAIL)+ {+ add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));+ return cc + 1;+ }++if (*cc == OP_ACCEPT && common->currententry == NULL && (common->re->overall_options & PCRE2_ENDANCHORED) != 0)+ add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0));++if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL || !common->might_be_empty)+ {+ /* No need to check notempty conditions. */+ if (common->accept_label == NULL)+ add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));+ else+ JUMPTO(SLJIT_JUMP, common->accept_label);+ return cc + 1;+ }++if (common->accept_label == NULL)+ add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)));+else+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label);++if (HAS_VIRTUAL_REGISTERS)+ {+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));+ }+else+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options));++OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);+add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_NOT_ZERO));+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);+if (common->accept_label == NULL)+ add_jump(compiler, &common->accept, JUMP(SLJIT_ZERO));+else+ JUMPTO(SLJIT_ZERO, common->accept_label);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));+if (common->accept_label == NULL)+ add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0));+else+ CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->accept_label);+add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));+return cc + 1;+}++static SLJIT_INLINE PCRE2_SPTR compile_close_matchingpath(compiler_common *common, PCRE2_SPTR cc)+{+DEFINE_COMPILER;+int offset = GET2(cc, 1);+BOOL optimized_cbracket = common->optimized_cbracket[offset] != 0;++/* Data will be discarded anyway... */+if (common->currententry != NULL)+ return cc + 1 + IMM2_SIZE;++if (!optimized_cbracket)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR_PRIV(offset));+offset <<= 1;+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+if (!optimized_cbracket)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+return cc + 1 + IMM2_SIZE;+}++static SLJIT_INLINE PCRE2_SPTR compile_control_verb_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+PCRE2_UCHAR opcode = *cc;+PCRE2_SPTR ccend = cc + 1;++if (opcode == OP_COMMIT_ARG || opcode == OP_PRUNE_ARG ||+ opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG)+ ccend += 2 + cc[1];++PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);++if (opcode == OP_SKIP)+ {+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ return ccend;+ }++if (opcode == OP_COMMIT_ARG || opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG)+ {+ if (HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);+ }++return ccend;+}++static PCRE2_UCHAR then_trap_opcode[1] = { OP_THEN_TRAP };++static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+BOOL needs_control_head;+int size;++PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc);+common->then_trap = BACKTRACK_AS(then_trap_backtrack);+BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode;+BACKTRACK_AS(then_trap_backtrack)->start = (sljit_sw)(cc - common->start);+BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, FALSE, &needs_control_head);++size = BACKTRACK_AS(then_trap_backtrack)->framesize;+size = 3 + (size < 0 ? 0 : size);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+allocate_stack(common, size);+if (size > 3)+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw));+else+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0);+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start);+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), SLJIT_IMM, type_then_trap);+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0);++size = BACKTRACK_AS(then_trap_backtrack)->framesize;+if (size >= 0)+ init_frame(common, cc, ccend, size - 1, 0);+}++static void compile_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, backtrack_common *parent)+{+DEFINE_COMPILER;+backtrack_common *backtrack;+BOOL has_then_trap = FALSE;+then_trap_backtrack *save_then_trap = NULL;++SLJIT_ASSERT(*ccend == OP_END || (*ccend >= OP_ALT && *ccend <= OP_KETRPOS));++if (common->has_then && common->then_offsets[cc - common->start] != 0)+ {+ SLJIT_ASSERT(*ccend != OP_END && common->control_head_ptr != 0);+ has_then_trap = TRUE;+ save_then_trap = common->then_trap;+ /* Tail item on backtrack. */+ compile_then_trap_matchingpath(common, cc, ccend, parent);+ }++while (cc < ccend)+ {+ switch(*cc)+ {+ case OP_SOD:+ case OP_SOM:+ case OP_NOT_WORD_BOUNDARY:+ case OP_WORD_BOUNDARY:+ case OP_EODN:+ case OP_EOD:+ case OP_DOLL:+ case OP_DOLLM:+ case OP_CIRC:+ case OP_CIRCM:+ case OP_REVERSE:+ cc = compile_simple_assertion_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);+ break;++ case OP_NOT_DIGIT:+ case OP_DIGIT:+ case OP_NOT_WHITESPACE:+ case OP_WHITESPACE:+ case OP_NOT_WORDCHAR:+ case OP_WORDCHAR:+ case OP_ANY:+ case OP_ALLANY:+ case OP_ANYBYTE:+ case OP_NOTPROP:+ case OP_PROP:+ case OP_ANYNL:+ case OP_NOT_HSPACE:+ case OP_HSPACE:+ case OP_NOT_VSPACE:+ case OP_VSPACE:+ case OP_EXTUNI:+ case OP_NOT:+ case OP_NOTI:+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);+ break;++ case OP_SET_SOM:+ PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);+ cc++;+ break;++ case OP_CHAR:+ case OP_CHARI:+ if (common->mode == PCRE2_JIT_COMPLETE)+ cc = compile_charn_matchingpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);+ else+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);+ break;++ case OP_STAR:+ case OP_MINSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSPLUS:+ case OP_POSQUERY:+ case OP_POSUPTO:+ case OP_STARI:+ case OP_MINSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_EXACTI:+ case OP_POSSTARI:+ case OP_POSPLUSI:+ case OP_POSQUERYI:+ case OP_POSUPTOI:+ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTEXACT:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSUPTO:+ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTEXACTI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSUPTOI:+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ case OP_TYPEPOSUPTO:+ cc = compile_iterator_matchingpath(common, cc, parent);+ break;++ case OP_CLASS:+ case OP_NCLASS:+ if (cc[1 + (32 / sizeof(PCRE2_UCHAR))] >= OP_CRSTAR && cc[1 + (32 / sizeof(PCRE2_UCHAR))] <= OP_CRPOSRANGE)+ cc = compile_iterator_matchingpath(common, cc, parent);+ else+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);+ break;++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ case OP_XCLASS:+ if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRPOSRANGE)+ cc = compile_iterator_matchingpath(common, cc, parent);+ else+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);+ break;+#endif++ case OP_REF:+ case OP_REFI:+ if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRPOSRANGE)+ cc = compile_ref_iterator_matchingpath(common, cc, parent);+ else+ {+ compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);+ cc += 1 + IMM2_SIZE;+ }+ break;++ case OP_DNREF:+ case OP_DNREFI:+ if (cc[1 + 2 * IMM2_SIZE] >= OP_CRSTAR && cc[1 + 2 * IMM2_SIZE] <= OP_CRPOSRANGE)+ cc = compile_ref_iterator_matchingpath(common, cc, parent);+ else+ {+ compile_dnref_search(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);+ compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);+ cc += 1 + 2 * IMM2_SIZE;+ }+ break;++ case OP_RECURSE:+ cc = compile_recurse_matchingpath(common, cc, parent);+ break;++ case OP_CALLOUT:+ case OP_CALLOUT_STR:+ cc = compile_callout_matchingpath(common, cc, parent);+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);+ cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);+ break;++ case OP_BRAMINZERO:+ PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc);+ cc = bracketend(cc + 1);+ if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)+ {+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);+ }+ else+ {+ allocate_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);+ }+ BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL();+ count_match(common);+ break;++ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRA:+ case OP_CBRA:+ case OP_COND:+ case OP_SBRA:+ case OP_SCBRA:+ case OP_SCOND:+ cc = compile_bracket_matchingpath(common, cc, parent);+ break;++ case OP_BRAZERO:+ if (cc[1] > OP_ASSERTBACK_NOT)+ cc = compile_bracket_matchingpath(common, cc, parent);+ else+ {+ PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);+ cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);+ }+ break;++ case OP_BRAPOS:+ case OP_CBRAPOS:+ case OP_SBRAPOS:+ case OP_SCBRAPOS:+ case OP_BRAPOSZERO:+ cc = compile_bracketpos_matchingpath(common, cc, parent);+ break;++ case OP_MARK:+ PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);+ SLJIT_ASSERT(common->mark_ptr != 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);+ allocate_stack(common, common->has_skip_arg ? 5 : 1);+ if (HAS_VIRTUAL_REGISTERS)+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);+ if (common->has_skip_arg)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_mark);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), SLJIT_IMM, (sljit_sw)(cc + 2));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);+ }+ cc += 1 + 2 + cc[1];+ break;++ case OP_PRUNE:+ case OP_PRUNE_ARG:+ case OP_SKIP:+ case OP_SKIP_ARG:+ case OP_THEN:+ case OP_THEN_ARG:+ case OP_COMMIT:+ case OP_COMMIT_ARG:+ cc = compile_control_verb_matchingpath(common, cc, parent);+ break;++ case OP_FAIL:+ case OP_ACCEPT:+ case OP_ASSERT_ACCEPT:+ cc = compile_fail_accept_matchingpath(common, cc, parent);+ break;++ case OP_CLOSE:+ cc = compile_close_matchingpath(common, cc);+ break;++ case OP_SKIPZERO:+ cc = bracketend(cc + 1);+ break;++ default:+ SLJIT_UNREACHABLE();+ return;+ }+ if (cc == NULL)+ return;+ }++if (has_then_trap)+ {+ /* Head item on backtrack. */+ PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc);+ BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode;+ BACKTRACK_AS(then_trap_backtrack)->then_trap = common->then_trap;+ common->then_trap = save_then_trap;+ }+SLJIT_ASSERT(cc == ccend);+}++#undef PUSH_BACKTRACK+#undef PUSH_BACKTRACK_NOVALUE+#undef BACKTRACK_AS++#define COMPILE_BACKTRACKINGPATH(current) \+ do \+ { \+ compile_backtrackingpath(common, (current)); \+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \+ return; \+ } \+ while (0)++#define CURRENT_AS(type) ((type *)current)++static void compile_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+PCRE2_SPTR cc = current->cc;+PCRE2_UCHAR opcode;+PCRE2_UCHAR type;+sljit_u32 max = 0, exact;+struct sljit_label *label = NULL;+struct sljit_jump *jump = NULL;+jump_list *jumplist = NULL;+PCRE2_SPTR end;+int private_data_ptr = PRIVATE_DATA(cc);+int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP);+int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr;+int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);++cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end);++switch(opcode)+ {+ case OP_STAR:+ case OP_UPTO:+ if (type == OP_ANYNL || type == OP_EXTUNI)+ {+ SLJIT_ASSERT(private_data_ptr == 0);+ set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ }+ else+ {+ if (CURRENT_AS(char_iterator_backtrack)->u.charpos.enabled)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ OP1(SLJIT_MOV, TMP2, 0, base, offset1);+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);+ label = LABEL();+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ if (CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit != 0)+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit);+ CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.chr, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ move_back(common, NULL, TRUE);+ CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP2, 0, label);+ }+ else+ {+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1);+ move_back(common, NULL, TRUE);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ }+ JUMPHERE(jump);+ if (private_data_ptr == 0)+ free_stack(common, 2);+ }+ break;++ case OP_MINSTAR:+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ set_jumps(jumplist, LABEL());+ if (private_data_ptr == 0)+ free_stack(common, 1);+ break;++ case OP_MINUPTO:+ OP1(SLJIT_MOV, TMP1, 0, base, offset1);+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+ add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO));++ OP1(SLJIT_MOV, base, offset1, TMP1, 0);+ compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);++ set_jumps(jumplist, LABEL());+ if (private_data_ptr == 0)+ free_stack(common, 2);+ break;++ case OP_QUERY:+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ jump = JUMP(SLJIT_JUMP);+ set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);+ JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ JUMPHERE(jump);+ if (private_data_ptr == 0)+ free_stack(common, 1);+ break;++ case OP_MINQUERY:+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);+ jump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);+ JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ set_jumps(jumplist, LABEL());+ JUMPHERE(jump);+ if (private_data_ptr == 0)+ free_stack(common, 1);+ break;++ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSQUERY:+ case OP_POSUPTO:+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++set_jumps(current->topbacktracks, LABEL());+}++static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+PCRE2_SPTR cc = current->cc;+BOOL ref = (*cc == OP_REF || *cc == OP_REFI);+PCRE2_UCHAR type;++type = cc[ref ? 1 + IMM2_SIZE : 1 + 2 * IMM2_SIZE];++if ((type & 0x1) == 0)+ {+ /* Maximize case. */+ set_jumps(current->topbacktracks, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath);+ return;+ }++OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath);+set_jumps(current->topbacktracks, LABEL());+free_stack(common, ref ? 2 : 3);+}++static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+recurse_entry *entry;++if (!CURRENT_AS(recurse_backtrack)->inlined_pattern)+ {+ entry = CURRENT_AS(recurse_backtrack)->entry;+ if (entry->backtrack_label == NULL)+ add_jump(compiler, &entry->backtrack_calls, JUMP(SLJIT_FAST_CALL));+ else+ JUMPTO(SLJIT_FAST_CALL, entry->backtrack_label);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(recurse_backtrack)->matchingpath);+ }+else+ compile_backtrackingpath(common, current->top);++set_jumps(current->topbacktracks, LABEL());+}++static void compile_assert_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+PCRE2_SPTR cc = current->cc;+PCRE2_UCHAR bra = OP_BRA;+struct sljit_jump *brajump = NULL;++SLJIT_ASSERT(*cc != OP_BRAMINZERO);+if (*cc == OP_BRAZERO)+ {+ bra = *cc;+ cc++;+ }++if (bra == OP_BRAZERO)+ {+ SLJIT_ASSERT(current->topbacktracks == NULL);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ }++if (CURRENT_AS(assert_backtrack)->framesize < 0)+ {+ set_jumps(current->topbacktracks, LABEL());++ if (bra == OP_BRAZERO)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath);+ free_stack(common, 1);+ }+ return;+ }++if (bra == OP_BRAZERO)+ {+ if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath);+ free_stack(common, 1);+ return;+ }+ free_stack(common, 1);+ brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);+ }++if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)+ {+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr);+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(assert_backtrack)->framesize - 1) * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, TMP1, 0);++ set_jumps(current->topbacktracks, LABEL());+ }+else+ set_jumps(current->topbacktracks, LABEL());++if (bra == OP_BRAZERO)+ {+ /* We know there is enough place on the stack. */+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->matchingpath);+ JUMPHERE(brajump);+ }+}++static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+int opcode, stacksize, alt_count, alt_max;+int offset = 0;+int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;+int repeat_ptr = 0, repeat_type = 0, repeat_count = 0;+PCRE2_SPTR cc = current->cc;+PCRE2_SPTR ccbegin;+PCRE2_SPTR ccprev;+PCRE2_UCHAR bra = OP_BRA;+PCRE2_UCHAR ket;+assert_backtrack *assert;+BOOL has_alternatives;+BOOL needs_control_head = FALSE;+struct sljit_jump *brazero = NULL;+struct sljit_jump *next_alt = NULL;+struct sljit_jump *once = NULL;+struct sljit_jump *cond = NULL;+struct sljit_label *rmin_label = NULL;+struct sljit_label *exact_label = NULL;+struct sljit_put_label *put_label = NULL;++if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)+ {+ bra = *cc;+ cc++;+ }++opcode = *cc;+ccbegin = bracketend(cc) - 1 - LINK_SIZE;+ket = *ccbegin;+if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0)+ {+ repeat_ptr = PRIVATE_DATA(ccbegin);+ repeat_type = PRIVATE_DATA(ccbegin + 2);+ repeat_count = PRIVATE_DATA(ccbegin + 3);+ SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0);+ if (repeat_type == OP_UPTO)+ ket = OP_KETRMAX;+ if (repeat_type == OP_MINUPTO)+ ket = OP_KETRMIN;+ }+ccbegin = cc;+cc += GET(cc, 1);+has_alternatives = *cc == OP_ALT;+if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))+ has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL;+if (opcode == OP_CBRA || opcode == OP_SCBRA)+ offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;+if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))+ opcode = OP_SCOND;++alt_max = has_alternatives ? no_alternatives(ccbegin) : 0;++/* Decoding the needs_control_head in framesize. */+if (opcode == OP_ONCE)+ {+ needs_control_head = (CURRENT_AS(bracket_backtrack)->u.framesize & 0x1) != 0;+ CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;+ }++if (ket != OP_KET && repeat_type != 0)+ {+ /* TMP1 is used in OP_KETRMIN below. */+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ if (repeat_type == OP_UPTO)+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0, SLJIT_IMM, 1);+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0);+ }++if (ket == OP_KETRMAX)+ {+ if (bra == OP_BRAZERO)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ brazero = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0);+ }+ }+else if (ket == OP_KETRMIN)+ {+ if (bra != OP_BRAMINZERO)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ if (repeat_type != 0)+ {+ /* TMP1 was set a few lines above. */+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);+ /* Drop STR_PTR for non-greedy plus quantifier. */+ if (opcode != OP_ONCE)+ free_stack(common, 1);+ }+ else if (opcode >= OP_SBRA || opcode == OP_ONCE)+ {+ /* Checking zero-length iteration. */+ if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 2), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);+ }+ /* Drop STR_PTR for non-greedy plus quantifier. */+ if (opcode != OP_ONCE)+ free_stack(common, 1);+ }+ else+ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);+ }+ rmin_label = LABEL();+ if (repeat_type != 0)+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);+ }+else if (bra == OP_BRAZERO)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ brazero = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);+ }+else if (repeat_type == OP_EXACT)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);+ exact_label = LABEL();+ }++if (offset != 0)+ {+ if (common->capture_last_ptr != 0)+ {+ SLJIT_ASSERT(common->optimized_cbracket[offset >> 1] == 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2));+ free_stack(common, 3);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP2, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);+ }+ else if (common->optimized_cbracket[offset >> 1] == 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ free_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);+ }+ }++if (SLJIT_UNLIKELY(opcode == OP_ONCE))+ {+ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)+ {+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(bracket_backtrack)->u.framesize - 1) * sizeof(sljit_sw));+ }+ once = JUMP(SLJIT_JUMP);+ }+else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))+ {+ if (has_alternatives)+ {+ /* Always exactly one alternative. */+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);++ alt_max = 2;+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);+ }+ }+else if (has_alternatives)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);++ if (alt_max > 3)+ {+ sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0);++ SLJIT_ASSERT(CURRENT_AS(bracket_backtrack)->u.matching_put_label);+ sljit_set_put_label(CURRENT_AS(bracket_backtrack)->u.matching_put_label, LABEL());+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ }+ else+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);+ }++COMPILE_BACKTRACKINGPATH(current->top);+if (current->topbacktracks)+ set_jumps(current->topbacktracks, LABEL());++if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))+ {+ /* Conditional block always has at most one alternative. */+ if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)+ {+ SLJIT_ASSERT(has_alternatives);+ assert = CURRENT_AS(bracket_backtrack)->u.assert;+ if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))+ {+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr);+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (assert->framesize - 1) * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, TMP1, 0);+ }+ cond = JUMP(SLJIT_JUMP);+ set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL());+ }+ else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL)+ {+ SLJIT_ASSERT(has_alternatives);+ cond = JUMP(SLJIT_JUMP);+ set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL());+ }+ else+ SLJIT_ASSERT(!has_alternatives);+ }++if (has_alternatives)+ {+ alt_count = 1;+ do+ {+ current->top = NULL;+ current->topbacktracks = NULL;+ current->nextbacktracks = NULL;+ /* Conditional blocks always have an additional alternative, even if it is empty. */+ if (*cc == OP_ALT)+ {+ ccprev = cc + 1 + LINK_SIZE;+ cc += GET(cc, 1);+ if (opcode != OP_COND && opcode != OP_SCOND)+ {+ if (opcode != OP_ONCE)+ {+ if (private_data_ptr != 0)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ else+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ }+ else+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0));+ }+ compile_matchingpath(common, ccprev, cc, current);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return;++ if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);++ if (opcode == OP_SCRIPT_RUN)+ match_script_run_common(common, private_data_ptr, current);+ }++ /* Instructions after the current alternative is successfully matched. */+ /* There is a similar code in compile_bracket_matchingpath. */+ if (opcode == OP_ONCE)+ match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);++ stacksize = 0;+ if (repeat_type == OP_MINUPTO)+ {+ /* We need to preserve the counter. TMP2 will be used below. */+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr);+ stacksize++;+ }+ if (ket != OP_KET || bra != OP_BRA)+ stacksize++;+ if (offset != 0)+ {+ if (common->capture_last_ptr != 0)+ stacksize++;+ if (common->optimized_cbracket[offset >> 1] == 0)+ stacksize += 2;+ }+ if (opcode != OP_ONCE)+ stacksize++;++ if (stacksize > 0)+ allocate_stack(common, stacksize);++ stacksize = 0;+ if (repeat_type == OP_MINUPTO)+ {+ /* TMP2 was set above. */+ OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);+ stacksize++;+ }++ if (ket != OP_KET || bra != OP_BRA)+ {+ if (ket != OP_KET)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);+ stacksize++;+ }++ if (offset != 0)+ stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);++ if (opcode != OP_ONCE)+ {+ if (alt_max <= 3)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count);+ else+ put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));+ }++ if (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0)+ {+ /* If ket is not OP_KETRMAX, this code path is executed after the jump to alternative_matchingpath. */+ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+ }++ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alternative_matchingpath);++ if (opcode != OP_ONCE)+ {+ if (alt_max <= 3)+ {+ JUMPHERE(next_alt);+ alt_count++;+ if (alt_count < alt_max)+ {+ SLJIT_ASSERT(alt_count == 2 && alt_max == 3);+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 1);+ }+ }+ else+ {+ sljit_set_put_label(put_label, LABEL());+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ }+ }++ COMPILE_BACKTRACKINGPATH(current->top);+ if (current->topbacktracks)+ set_jumps(current->topbacktracks, LABEL());+ SLJIT_ASSERT(!current->nextbacktracks);+ }+ while (*cc == OP_ALT);++ if (cond != NULL)+ {+ SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);+ assert = CURRENT_AS(bracket_backtrack)->u.assert;+ if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0)+ {+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr);+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (assert->framesize - 1) * sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, TMP1, 0);+ }+ JUMPHERE(cond);+ }++ /* Free the STR_PTR. */+ if (private_data_ptr == 0)+ free_stack(common, 1);+ }++if (offset != 0)+ {+ /* Using both tmp register is better for instruction scheduling. */+ if (common->optimized_cbracket[offset >> 1] != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ free_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);+ }+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }+ }+else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ }+else if (opcode == OP_ONCE)+ {+ cc = ccbegin + GET(ccbegin, 1);+ stacksize = needs_control_head ? 1 : 0;++ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)+ {+ /* Reset head and drop saved frame. */+ stacksize += CURRENT_AS(bracket_backtrack)->u.framesize + ((ket != OP_KET || *cc == OP_ALT) ? 2 : 1);+ }+ else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))+ {+ /* The STR_PTR must be released. */+ stacksize++;+ }++ if (stacksize > 0)+ free_stack(common, stacksize);++ JUMPHERE(once);+ /* Restore previous private_data_ptr */+ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 1));+ else if (ket == OP_KETRMIN)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ /* See the comment below. */+ free_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);+ }+ }++if (repeat_type == OP_EXACT)+ {+ OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0);+ CMPTO(SLJIT_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label);+ }+else if (ket == OP_KETRMAX)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ if (bra != OP_BRAZERO)+ free_stack(common, 1);++ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);+ if (bra == OP_BRAZERO)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath);+ JUMPHERE(brazero);+ free_stack(common, 1);+ }+ }+else if (ket == OP_KETRMIN)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));++ /* OP_ONCE removes everything in case of a backtrack, so we don't+ need to explicitly release the STR_PTR. The extra release would+ affect badly the free_stack(2) above. */+ if (opcode != OP_ONCE)+ free_stack(common, 1);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label);+ if (opcode == OP_ONCE)+ free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);+ else if (bra == OP_BRAMINZERO)+ free_stack(common, 1);+ }+else if (bra == OP_BRAZERO)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath);+ JUMPHERE(brazero);+ }+}++static SLJIT_INLINE void compile_bracketpos_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+int offset;+struct sljit_jump *jump;++if (CURRENT_AS(bracketpos_backtrack)->framesize < 0)+ {+ if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS)+ {+ offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0);+ if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0);+ if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0);+ }+ set_jumps(current->topbacktracks, LABEL());+ free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);+ return;+ }++OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr);+add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(bracketpos_backtrack)->framesize - 1) * sizeof(sljit_sw));++if (current->topbacktracks)+ {+ jump = JUMP(SLJIT_JUMP);+ set_jumps(current->topbacktracks, LABEL());+ /* Drop the stack frame. */+ free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);+ JUMPHERE(jump);+ }+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracketpos_backtrack)->framesize - 1));+}++static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+assert_backtrack backtrack;++current->top = NULL;+current->topbacktracks = NULL;+current->nextbacktracks = NULL;+if (current->cc[1] > OP_ASSERTBACK_NOT)+ {+ /* Manual call of compile_bracket_matchingpath and compile_bracket_backtrackingpath. */+ compile_bracket_matchingpath(common, current->cc, current);+ compile_bracket_backtrackingpath(common, current->top);+ }+else+ {+ memset(&backtrack, 0, sizeof(backtrack));+ backtrack.common.cc = current->cc;+ backtrack.matchingpath = CURRENT_AS(braminzero_backtrack)->matchingpath;+ /* Manual call of compile_assert_matchingpath. */+ compile_assert_matchingpath(common, current->cc, &backtrack, FALSE);+ }+SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks);+}++static SLJIT_INLINE void compile_control_verb_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+PCRE2_UCHAR opcode = *current->cc;+struct sljit_label *loop;+struct sljit_jump *jump;++if (opcode == OP_THEN || opcode == OP_THEN_ARG)+ {+ if (common->then_trap != NULL)+ {+ SLJIT_ASSERT(common->control_head_ptr != 0);++ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start);+ jump = JUMP(SLJIT_JUMP);++ loop = LABEL();+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ JUMPHERE(jump);+ CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0, loop);+ CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0, loop);+ add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));+ return;+ }+ else if (!common->local_quit_available && common->in_positive_assertion)+ {+ add_jump(compiler, &common->positive_assertion_quit, JUMP(SLJIT_JUMP));+ return;+ }+ }++if (common->local_quit_available)+ {+ /* Abort match with a fail. */+ if (common->quit_label == NULL)+ add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));+ else+ JUMPTO(SLJIT_JUMP, common->quit_label);+ return;+ }++if (opcode == OP_SKIP_ARG)+ {+ SLJIT_ASSERT(common->control_head_ptr != 0 && TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);+ OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark));++ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_R0, 0);+ add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0));+ return;+ }++if (opcode == OP_SKIP)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+else+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_IMM, 0);+add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP));+}++static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+struct sljit_jump *jump;+int size;++if (CURRENT_AS(then_trap_backtrack)->then_trap)+ {+ common->then_trap = CURRENT_AS(then_trap_backtrack)->then_trap;+ return;+ }++size = CURRENT_AS(then_trap_backtrack)->framesize;+size = 3 + (size < 0 ? 0 : size);++OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(size - 3));+free_stack(common, size);+jump = JUMP(SLJIT_JUMP);++set_jumps(CURRENT_AS(then_trap_backtrack)->quit, LABEL());+/* STACK_TOP is set by THEN. */+if (CURRENT_AS(then_trap_backtrack)->framesize >= 0)+ {+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(then_trap_backtrack)->framesize - 1) * sizeof(sljit_sw));+ }+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+free_stack(common, 3);++JUMPHERE(jump);+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0);+}++static void compile_backtrackingpath(compiler_common *common, struct backtrack_common *current)+{+DEFINE_COMPILER;+then_trap_backtrack *save_then_trap = common->then_trap;++while (current)+ {+ if (current->nextbacktracks != NULL)+ set_jumps(current->nextbacktracks, LABEL());+ switch(*current->cc)+ {+ case OP_SET_SOM:+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), TMP1, 0);+ break;++ case OP_STAR:+ case OP_MINSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSPLUS:+ case OP_POSQUERY:+ case OP_POSUPTO:+ case OP_STARI:+ case OP_MINSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_EXACTI:+ case OP_POSSTARI:+ case OP_POSPLUSI:+ case OP_POSQUERYI:+ case OP_POSUPTOI:+ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTEXACT:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSUPTO:+ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTEXACTI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSUPTOI:+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ case OP_TYPEPOSUPTO:+ case OP_CLASS:+ case OP_NCLASS:+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+#endif+ compile_iterator_backtrackingpath(common, current);+ break;++ case OP_REF:+ case OP_REFI:+ case OP_DNREF:+ case OP_DNREFI:+ compile_ref_iterator_backtrackingpath(common, current);+ break;++ case OP_RECURSE:+ compile_recurse_backtrackingpath(common, current);+ break;++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ compile_assert_backtrackingpath(common, current);+ break;++ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_BRA:+ case OP_CBRA:+ case OP_COND:+ case OP_SBRA:+ case OP_SCBRA:+ case OP_SCOND:+ compile_bracket_backtrackingpath(common, current);+ break;++ case OP_BRAZERO:+ if (current->cc[1] > OP_ASSERTBACK_NOT)+ compile_bracket_backtrackingpath(common, current);+ else+ compile_assert_backtrackingpath(common, current);+ break;++ case OP_BRAPOS:+ case OP_CBRAPOS:+ case OP_SBRAPOS:+ case OP_SCBRAPOS:+ case OP_BRAPOSZERO:+ compile_bracketpos_backtrackingpath(common, current);+ break;++ case OP_BRAMINZERO:+ compile_braminzero_backtrackingpath(common, current);+ break;++ case OP_MARK:+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0));+ if (common->has_skip_arg)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ free_stack(common, common->has_skip_arg ? 5 : 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP1, 0);+ if (common->has_skip_arg)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0);+ break;++ case OP_THEN:+ case OP_THEN_ARG:+ case OP_PRUNE:+ case OP_PRUNE_ARG:+ case OP_SKIP:+ case OP_SKIP_ARG:+ compile_control_verb_backtrackingpath(common, current);+ break;++ case OP_COMMIT:+ case OP_COMMIT_ARG:+ if (!common->local_quit_available)+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);+ if (common->quit_label == NULL)+ add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));+ else+ JUMPTO(SLJIT_JUMP, common->quit_label);+ break;++ case OP_CALLOUT:+ case OP_CALLOUT_STR:+ case OP_FAIL:+ case OP_ACCEPT:+ case OP_ASSERT_ACCEPT:+ set_jumps(current->topbacktracks, LABEL());+ break;++ case OP_THEN_TRAP:+ /* A virtual opcode for then traps. */+ compile_then_trap_backtrackingpath(common, current);+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }+ current = current->prev;+ }+common->then_trap = save_then_trap;+}++static SLJIT_INLINE void compile_recurse(compiler_common *common)+{+DEFINE_COMPILER;+PCRE2_SPTR cc = common->start + common->currententry->start;+PCRE2_SPTR ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE);+PCRE2_SPTR ccend = bracketend(cc) - (1 + LINK_SIZE);+BOOL needs_control_head;+BOOL has_quit;+BOOL has_accept;+int private_data_size = get_recurse_data_length(common, ccbegin, ccend, &needs_control_head, &has_quit, &has_accept);+int alt_count, alt_max, local_size;+backtrack_common altbacktrack;+jump_list *match = NULL;+struct sljit_jump *next_alt = NULL;+struct sljit_jump *accept_exit = NULL;+struct sljit_label *quit;+struct sljit_put_label *put_label = NULL;++/* Recurse captures then. */+common->then_trap = NULL;++SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);++alt_max = no_alternatives(cc);+alt_count = 0;++/* Matching path. */+SLJIT_ASSERT(common->currententry->entry_label == NULL && common->recursive_head_ptr != 0);+common->currententry->entry_label = LABEL();+set_jumps(common->currententry->entry_calls, common->currententry->entry_label);++sljit_emit_fast_enter(compiler, TMP2, 0);+count_match(common);++local_size = (alt_max > 1) ? 2 : 1;++/* (Reversed) stack layout:+ [private data][return address][optional: str ptr] ... [optional: alternative index][recursive_head_ptr] */++allocate_stack(common, private_data_size + local_size);+/* Save return address. */+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1), TMP2, 0);++copy_recurse_data(common, ccbegin, ccend, recurse_copy_from_global, local_size, private_data_size + local_size, has_quit);++/* This variable is saved and restored all time when we enter or exit from a recursive context. */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0);++if (needs_control_head)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);++if (alt_max > 1)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);++memset(&altbacktrack, 0, sizeof(backtrack_common));+common->quit_label = NULL;+common->accept_label = NULL;+common->quit = NULL;+common->accept = NULL;+altbacktrack.cc = ccbegin;+cc += GET(cc, 1);+while (1)+ {+ altbacktrack.top = NULL;+ altbacktrack.topbacktracks = NULL;++ if (altbacktrack.cc != ccbegin)+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));++ compile_matchingpath(common, altbacktrack.cc, cc, &altbacktrack);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return;++ allocate_stack(common, (alt_max > 1 || has_accept) ? 2 : 1);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);++ if (alt_max > 1 || has_accept)+ {+ if (alt_max > 3)+ put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(1));+ else+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count);+ }++ add_jump(compiler, &match, JUMP(SLJIT_JUMP));++ if (alt_count == 0)+ {+ /* Backtracking path entry. */+ SLJIT_ASSERT(common->currententry->backtrack_label == NULL);+ common->currententry->backtrack_label = LABEL();+ set_jumps(common->currententry->backtrack_calls, common->currententry->backtrack_label);++ sljit_emit_fast_enter(compiler, TMP1, 0);++ if (has_accept)+ accept_exit = CMP(SLJIT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);++ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));+ /* Save return address. */+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(local_size - 1), TMP1, 0);++ copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, has_quit);++ if (alt_max > 1)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));+ free_stack(common, 2);++ if (alt_max > 3)+ {+ sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0);+ sljit_set_put_label(put_label, LABEL());+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ }+ else+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);+ }+ else+ free_stack(common, has_accept ? 2 : 1);+ }+ else if (alt_max > 3)+ {+ sljit_set_put_label(put_label, LABEL());+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ }+ else+ {+ JUMPHERE(next_alt);+ if (alt_count + 1 < alt_max)+ {+ SLJIT_ASSERT(alt_count == 1 && alt_max == 3);+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 1);+ }+ }++ alt_count++;++ compile_backtrackingpath(common, altbacktrack.top);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return;+ set_jumps(altbacktrack.topbacktracks, LABEL());++ if (*cc != OP_ALT)+ break;++ altbacktrack.cc = cc + 1 + LINK_SIZE;+ cc += GET(cc, 1);+ }++/* No alternative is matched. */++quit = LABEL();++copy_recurse_data(common, ccbegin, ccend, recurse_copy_private_to_global, local_size, private_data_size + local_size, has_quit);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1));+free_stack(common, private_data_size + local_size);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+OP_SRC(SLJIT_FAST_RETURN, TMP2, 0);++if (common->quit != NULL)+ {+ SLJIT_ASSERT(has_quit);++ set_jumps(common->quit, LABEL());+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);+ copy_recurse_data(common, ccbegin, ccend, recurse_copy_shared_to_global, local_size, private_data_size + local_size, has_quit);+ JUMPTO(SLJIT_JUMP, quit);+ }++if (has_accept)+ {+ JUMPHERE(accept_exit);+ free_stack(common, 2);++ /* Save return address. */+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1), TMP1, 0);++ copy_recurse_data(common, ccbegin, ccend, recurse_copy_kept_shared_to_global, local_size, private_data_size + local_size, has_quit);++ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1));+ free_stack(common, private_data_size + local_size);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);+ OP_SRC(SLJIT_FAST_RETURN, TMP2, 0);+ }++if (common->accept != NULL)+ {+ SLJIT_ASSERT(has_accept);++ set_jumps(common->accept, LABEL());++ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);+ OP1(SLJIT_MOV, TMP2, 0, STACK_TOP, 0);++ allocate_stack(common, 2);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);+ }++set_jumps(match, LABEL());++OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);++copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, has_quit);++OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), STACK(local_size - 1));+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);+OP_SRC(SLJIT_FAST_RETURN, TMP2, 0);+}++#undef COMPILE_BACKTRACKINGPATH+#undef CURRENT_AS++#define PUBLIC_JIT_COMPILE_CONFIGURATION_OPTIONS \+ (PCRE2_JIT_INVALID_UTF)++static int jit_compile(pcre2_code *code, sljit_u32 mode)+{+pcre2_real_code *re = (pcre2_real_code *)code;+struct sljit_compiler *compiler;+backtrack_common rootbacktrack;+compiler_common common_data;+compiler_common *common = &common_data;+const sljit_u8 *tables = re->tables;+void *allocator_data = &re->memctl;+int private_data_size;+PCRE2_SPTR ccend;+executable_functions *functions;+void *executable_func;+sljit_uw executable_size;+sljit_uw total_length;+struct sljit_label *mainloop_label = NULL;+struct sljit_label *continue_match_label;+struct sljit_label *empty_match_found_label = NULL;+struct sljit_label *empty_match_backtrack_label = NULL;+struct sljit_label *reset_match_label;+struct sljit_label *quit_label;+struct sljit_jump *jump;+struct sljit_jump *minlength_check_failed = NULL;+struct sljit_jump *empty_match = NULL;+struct sljit_jump *end_anchor_failed = NULL;+jump_list *reqcu_not_found = NULL;++SLJIT_ASSERT(tables);++#if HAS_VIRTUAL_REGISTERS == 1+SLJIT_ASSERT(sljit_get_register_index(TMP3) < 0 && sljit_get_register_index(ARGUMENTS) < 0 && sljit_get_register_index(RETURN_ADDR) < 0);+#elif HAS_VIRTUAL_REGISTERS == 0+SLJIT_ASSERT(sljit_get_register_index(TMP3) >= 0 && sljit_get_register_index(ARGUMENTS) >= 0 && sljit_get_register_index(RETURN_ADDR) >= 0);+#else+#error "Invalid value for HAS_VIRTUAL_REGISTERS"+#endif++memset(&rootbacktrack, 0, sizeof(backtrack_common));+memset(common, 0, sizeof(compiler_common));+common->re = re;+common->name_table = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));+rootbacktrack.cc = common->name_table + re->name_count * re->name_entry_size;++#ifdef SUPPORT_UNICODE+common->invalid_utf = (mode & PCRE2_JIT_INVALID_UTF) != 0;+#endif /* SUPPORT_UNICODE */+mode &= ~PUBLIC_JIT_COMPILE_CONFIGURATION_OPTIONS;++common->start = rootbacktrack.cc;+common->read_only_data_head = NULL;+common->fcc = tables + fcc_offset;+common->lcc = (sljit_sw)(tables + lcc_offset);+common->mode = mode;+common->might_be_empty = (re->minlength == 0) || (re->flags & PCRE2_MATCH_EMPTY);+common->allow_empty_partial = (re->max_lookbehind > 0) || (re->flags & PCRE2_MATCH_EMPTY);+common->nltype = NLTYPE_FIXED;+switch(re->newline_convention)+ {+ case PCRE2_NEWLINE_CR: common->newline = CHAR_CR; break;+ case PCRE2_NEWLINE_LF: common->newline = CHAR_NL; break;+ case PCRE2_NEWLINE_CRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;+ case PCRE2_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;+ case PCRE2_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;+ case PCRE2_NEWLINE_NUL: common->newline = CHAR_NUL; break;+ default: return PCRE2_ERROR_INTERNAL;+ }+common->nlmax = READ_CHAR_MAX;+common->nlmin = 0;+if (re->bsr_convention == PCRE2_BSR_UNICODE)+ common->bsr_nltype = NLTYPE_ANY;+else if (re->bsr_convention == PCRE2_BSR_ANYCRLF)+ common->bsr_nltype = NLTYPE_ANYCRLF;+else+ {+#ifdef BSR_ANYCRLF+ common->bsr_nltype = NLTYPE_ANYCRLF;+#else+ common->bsr_nltype = NLTYPE_ANY;+#endif+ }+common->bsr_nlmax = READ_CHAR_MAX;+common->bsr_nlmin = 0;+common->endonly = (re->overall_options & PCRE2_DOLLAR_ENDONLY) != 0;+common->ctypes = (sljit_sw)(tables + ctypes_offset);+common->name_count = re->name_count;+common->name_entry_size = re->name_entry_size;+common->unset_backref = (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) != 0;+common->alt_circumflex = (re->overall_options & PCRE2_ALT_CIRCUMFLEX) != 0;+#ifdef SUPPORT_UNICODE+/* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */+common->utf = (re->overall_options & PCRE2_UTF) != 0;+common->ucp = (re->overall_options & PCRE2_UCP) != 0;+if (common->utf)+ {+ if (common->nltype == NLTYPE_ANY)+ common->nlmax = 0x2029;+ else if (common->nltype == NLTYPE_ANYCRLF)+ common->nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;+ else+ {+ /* We only care about the first newline character. */+ common->nlmax = common->newline & 0xff;+ }++ if (common->nltype == NLTYPE_FIXED)+ common->nlmin = common->newline & 0xff;+ else+ common->nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;++ if (common->bsr_nltype == NLTYPE_ANY)+ common->bsr_nlmax = 0x2029;+ else+ common->bsr_nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;+ common->bsr_nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;+ }+else+ common->invalid_utf = FALSE;+#endif /* SUPPORT_UNICODE */+ccend = bracketend(common->start);++/* Calculate the local space size on the stack. */+common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw);+common->optimized_cbracket = (sljit_u8 *)SLJIT_MALLOC(re->top_bracket + 1, allocator_data);+if (!common->optimized_cbracket)+ return PCRE2_ERROR_NOMEMORY;+#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1+memset(common->optimized_cbracket, 0, re->top_bracket + 1);+#else+memset(common->optimized_cbracket, 1, re->top_bracket + 1);+#endif++SLJIT_ASSERT(*common->start == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);+#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 2+common->capture_last_ptr = common->ovector_start;+common->ovector_start += sizeof(sljit_sw);+#endif+if (!check_opcode_types(common, common->start, ccend))+ {+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }++/* Checking flags and updating ovector_start. */+if (mode == PCRE2_JIT_COMPLETE && (re->flags & PCRE2_LASTSET) != 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)+ {+ common->req_char_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+if (mode != PCRE2_JIT_COMPLETE)+ {+ common->start_used_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ if (mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ common->hit_start = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+ }+if ((re->overall_options & (PCRE2_FIRSTLINE | PCRE2_USE_OFFSET_LIMIT)) != 0)+ {+ common->match_end_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD+common->control_head_ptr = 1;+#endif+if (common->control_head_ptr != 0)+ {+ common->control_head_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }+if (common->has_set_som)+ {+ /* Saving the real start pointer is necessary. */+ common->start_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }++/* Aligning ovector to even number of sljit words. */+if ((common->ovector_start & sizeof(sljit_sw)) != 0)+ common->ovector_start += sizeof(sljit_sw);++if (common->start_ptr == 0)+ common->start_ptr = OVECTOR(0);++/* Capturing brackets cannot be optimized if callouts are allowed. */+if (common->capture_last_ptr != 0)+ memset(common->optimized_cbracket, 0, re->top_bracket + 1);++SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));+common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);++total_length = ccend - common->start;+common->private_data_ptrs = (sljit_s32 *)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data);+if (!common->private_data_ptrs)+ {+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }+memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32));++private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);+set_private_data_ptrs(common, &private_data_size, ccend);+if ((re->overall_options & PCRE2_ANCHORED) == 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 && !common->has_skip_in_assert_back)+ detect_early_fail(common, common->start, &private_data_size, 0, 0);++SLJIT_ASSERT(common->early_fail_start_ptr <= common->early_fail_end_ptr);++if (private_data_size > SLJIT_MAX_LOCAL_SIZE)+ {+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }++if (common->has_then)+ {+ common->then_offsets = (sljit_u8 *)(common->private_data_ptrs + total_length);+ memset(common->then_offsets, 0, total_length);+ set_then_offsets(common, common->start, NULL);+ }++compiler = sljit_create_compiler(allocator_data, NULL);+if (!compiler)+ {+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }+common->compiler = compiler;++/* Main pcre_jit_exec entry. */+sljit_emit_enter(compiler, 0, SLJIT_ARG1(SW), 5, 5, 0, 0, private_data_size);++/* Register init. */+reset_ovector(common, (re->top_bracket + 1) * 2);+if (common->req_char_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, SLJIT_R0, 0);++OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_S0, 0);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_S0, 0);+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));+OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));+OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match));+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, end));+OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, start));+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0);++if (common->early_fail_start_ptr < common->early_fail_end_ptr)+ reset_early_fail(common);++if (mode == PCRE2_JIT_PARTIAL_SOFT)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);+if (common->mark_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);+if (common->control_head_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);++/* Main part of the matching */+if ((re->overall_options & PCRE2_ANCHORED) == 0)+ {+ mainloop_label = mainloop_entry(common);+ continue_match_label = LABEL();+ /* Forward search if possible. */+ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)+ {+ if (mode == PCRE2_JIT_COMPLETE && fast_forward_first_n_chars(common))+ ;+ else if ((re->flags & PCRE2_FIRSTSET) != 0)+ fast_forward_first_char(common);+ else if ((re->flags & PCRE2_STARTLINE) != 0)+ fast_forward_newline(common);+ else if ((re->flags & PCRE2_FIRSTMAPSET) != 0)+ fast_forward_start_bits(common);+ }+ }+else+ continue_match_label = LABEL();++if (mode == PCRE2_JIT_COMPLETE && re->minlength > 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)+ {+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(re->minlength));+ minlength_check_failed = CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0);+ }+if (common->req_char_ptr != 0)+ reqcu_not_found = search_requested_char(common, (PCRE2_UCHAR)(re->last_codeunit), (re->flags & PCRE2_LASTCASELESS) != 0, (re->flags & PCRE2_FIRSTSET) != 0);++/* Store the current STR_PTR in OVECTOR(0). */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0);+/* Copy the limit of allowed recursions. */+OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH);+if (common->capture_last_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, 0);+if (common->fast_forward_bc_ptr != NULL)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), PRIVATE_DATA(common->fast_forward_bc_ptr + 1) >> 3, STR_PTR, 0);++if (common->start_ptr != OVECTOR(0))+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0);++/* Copy the beginning of the string. */+if (mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);+ JUMPHERE(jump);+ }+else if (mode == PCRE2_JIT_PARTIAL_HARD)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);++compile_matchingpath(common, common->start, ccend, &rootbacktrack);+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ {+ sljit_free_compiler(compiler);+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }++if ((re->overall_options & PCRE2_ENDANCHORED) != 0)+ end_anchor_failed = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0);++if (common->might_be_empty)+ {+ empty_match = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));+ empty_match_found_label = LABEL();+ }++common->accept_label = LABEL();+if (common->accept != NULL)+ set_jumps(common->accept, common->accept_label);++/* This means we have a match. Update the ovector. */+copy_ovector(common, re->top_bracket + 1);+common->quit_label = common->abort_label = LABEL();+if (common->quit != NULL)+ set_jumps(common->quit, common->quit_label);+if (common->abort != NULL)+ set_jumps(common->abort, common->abort_label);+if (minlength_check_failed != NULL)+ SET_LABEL(minlength_check_failed, common->abort_label);++sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN);+sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++if (common->failed_match != NULL)+ {+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);+ set_jumps(common->failed_match, LABEL());+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);+ JUMPTO(SLJIT_JUMP, common->abort_label);+ }++if ((re->overall_options & PCRE2_ENDANCHORED) != 0)+ JUMPHERE(end_anchor_failed);++if (mode != PCRE2_JIT_COMPLETE)+ {+ common->partialmatchlabel = LABEL();+ set_jumps(common->partialmatch, common->partialmatchlabel);+ return_with_partial_match(common, common->quit_label);+ }++if (common->might_be_empty)+ empty_match_backtrack_label = LABEL();+compile_backtrackingpath(common, rootbacktrack.top);+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ {+ sljit_free_compiler(compiler);+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }++SLJIT_ASSERT(rootbacktrack.prev == NULL);+reset_match_label = LABEL();++if (mode == PCRE2_JIT_PARTIAL_SOFT)+ {+ /* Update hit_start only in the first time. */+ jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, TMP1, 0);+ JUMPHERE(jump);+ }++/* Check we have remaining characters. */+if ((re->overall_options & PCRE2_ANCHORED) == 0 && common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ }++OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP),+ (common->fast_forward_bc_ptr != NULL) ? (PRIVATE_DATA(common->fast_forward_bc_ptr + 1) >> 3) : common->start_ptr);++if ((re->overall_options & PCRE2_ANCHORED) == 0)+ {+ if (common->ff_newline_shortcut != NULL)+ {+ /* There cannot be more newlines if PCRE2_FIRSTLINE is set. */+ if ((re->overall_options & PCRE2_FIRSTLINE) == 0)+ {+ if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);+ OP1(SLJIT_MOV, STR_END, 0, TMP1, 0);+ CMPTO(SLJIT_LESS, STR_PTR, 0, TMP1, 0, common->ff_newline_shortcut);+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+ }+ else+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut);+ }+ }+ else+ CMPTO(SLJIT_LESS, STR_PTR, 0, (common->match_end_ptr == 0) ? STR_END : TMP1, 0, mainloop_label);+ }++/* No more remaining characters. */+if (reqcu_not_found != NULL)+ set_jumps(reqcu_not_found, LABEL());++if (mode == PCRE2_JIT_PARTIAL_SOFT)+ CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel);++OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);+JUMPTO(SLJIT_JUMP, common->quit_label);++flush_stubs(common);++if (common->might_be_empty)+ {+ JUMPHERE(empty_match);+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);+ JUMPTO(SLJIT_NOT_ZERO, empty_match_backtrack_label);+ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);+ JUMPTO(SLJIT_ZERO, empty_match_found_label);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));+ CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label);+ JUMPTO(SLJIT_JUMP, empty_match_backtrack_label);+ }++common->fast_forward_bc_ptr = NULL;+common->early_fail_start_ptr = 0;+common->early_fail_end_ptr = 0;+common->currententry = common->entries;+common->local_quit_available = TRUE;+quit_label = common->quit_label;+while (common->currententry != NULL)+ {+ /* Might add new entries. */+ compile_recurse(common);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ {+ sljit_free_compiler(compiler);+ SLJIT_FREE(common->optimized_cbracket, allocator_data);+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }+ flush_stubs(common);+ common->currententry = common->currententry->next;+ }+common->local_quit_available = FALSE;+common->quit_label = quit_label;++/* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */+/* This is a (really) rare case. */+set_jumps(common->stackalloc, LABEL());+/* RETURN_ADDR is not a saved register. */+sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);++SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);++OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0);+OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);+OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE);+OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack));+OP1(SLJIT_MOV, STACK_LIMIT, 0, TMP2, 0);++sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));++jump = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0);+OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0);+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);+OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);++/* Allocation failed. */+JUMPHERE(jump);+/* We break the return address cache here, but this is a really rare case. */+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_JIT_STACKLIMIT);+JUMPTO(SLJIT_JUMP, common->quit_label);++/* Call limit reached. */+set_jumps(common->calllimit, LABEL());+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_MATCHLIMIT);+JUMPTO(SLJIT_JUMP, common->quit_label);++if (common->revertframes != NULL)+ {+ set_jumps(common->revertframes, LABEL());+ do_revertframes(common);+ }+if (common->wordboundary != NULL)+ {+ set_jumps(common->wordboundary, LABEL());+ check_wordboundary(common);+ }+if (common->anynewline != NULL)+ {+ set_jumps(common->anynewline, LABEL());+ check_anynewline(common);+ }+if (common->hspace != NULL)+ {+ set_jumps(common->hspace, LABEL());+ check_hspace(common);+ }+if (common->vspace != NULL)+ {+ set_jumps(common->vspace, LABEL());+ check_vspace(common);+ }+if (common->casefulcmp != NULL)+ {+ set_jumps(common->casefulcmp, LABEL());+ do_casefulcmp(common);+ }+if (common->caselesscmp != NULL)+ {+ set_jumps(common->caselesscmp, LABEL());+ do_caselesscmp(common);+ }+if (common->reset_match != NULL)+ {+ set_jumps(common->reset_match, LABEL());+ do_reset_match(common, (re->top_bracket + 1) * 2);+ CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP1, 0, continue_match_label);+ OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);+ JUMPTO(SLJIT_JUMP, reset_match_label);+ }+#ifdef SUPPORT_UNICODE+#if PCRE2_CODE_UNIT_WIDTH == 8+if (common->utfreadchar != NULL)+ {+ set_jumps(common->utfreadchar, LABEL());+ do_utfreadchar(common);+ }+if (common->utfreadtype8 != NULL)+ {+ set_jumps(common->utfreadtype8, LABEL());+ do_utfreadtype8(common);+ }+if (common->utfpeakcharback != NULL)+ {+ set_jumps(common->utfpeakcharback, LABEL());+ do_utfpeakcharback(common);+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16+if (common->utfreadchar_invalid != NULL)+ {+ set_jumps(common->utfreadchar_invalid, LABEL());+ do_utfreadchar_invalid(common);+ }+if (common->utfreadnewline_invalid != NULL)+ {+ set_jumps(common->utfreadnewline_invalid, LABEL());+ do_utfreadnewline_invalid(common);+ }+if (common->utfmoveback_invalid)+ {+ set_jumps(common->utfmoveback_invalid, LABEL());+ do_utfmoveback_invalid(common);+ }+if (common->utfpeakcharback_invalid)+ {+ set_jumps(common->utfpeakcharback_invalid, LABEL());+ do_utfpeakcharback_invalid(common);+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16 */+if (common->getucd != NULL)+ {+ set_jumps(common->getucd, LABEL());+ do_getucd(common);+ }+if (common->getucdtype != NULL)+ {+ set_jumps(common->getucdtype, LABEL());+ do_getucdtype(common);+ }+#endif /* SUPPORT_UNICODE */++SLJIT_FREE(common->optimized_cbracket, allocator_data);+SLJIT_FREE(common->private_data_ptrs, allocator_data);++executable_func = sljit_generate_code(compiler);+executable_size = sljit_get_generated_code_size(compiler);+sljit_free_compiler(compiler);++if (executable_func == NULL)+ {+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }++/* Reuse the function descriptor if possible. */+if (re->executable_jit != NULL)+ functions = (executable_functions *)re->executable_jit;+else+ {+ functions = SLJIT_MALLOC(sizeof(executable_functions), allocator_data);+ if (functions == NULL)+ {+ /* This case is highly unlikely since we just recently+ freed a lot of memory. Not impossible though. */+ sljit_free_code(executable_func, NULL);+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }+ memset(functions, 0, sizeof(executable_functions));+ functions->top_bracket = re->top_bracket + 1;+ functions->limit_match = re->limit_match;+ re->executable_jit = functions;+ }++/* Turn mode into an index. */+if (mode == PCRE2_JIT_COMPLETE)+ mode = 0;+else+ mode = (mode == PCRE2_JIT_PARTIAL_SOFT) ? 1 : 2;++SLJIT_ASSERT(mode < JIT_NUMBER_OF_COMPILE_MODES);+functions->executable_funcs[mode] = executable_func;+functions->read_only_data_heads[mode] = common->read_only_data_head;+functions->executable_sizes[mode] = executable_size;+return 0;+}++#endif++/*************************************************+* JIT compile a Regular Expression *+*************************************************/++/* This function used JIT to convert a previously-compiled pattern into machine+code.++Arguments:+ code a compiled pattern+ options JIT option bits++Returns: 0: success or (*NOJIT) was used+ <0: an error code+*/++#define PUBLIC_JIT_COMPILE_OPTIONS \+ (PCRE2_JIT_COMPLETE|PCRE2_JIT_PARTIAL_SOFT|PCRE2_JIT_PARTIAL_HARD|PCRE2_JIT_INVALID_UTF)++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_jit_compile(pcre2_code *code, uint32_t options)+{+pcre2_real_code *re = (pcre2_real_code *)code;++if (code == NULL)+ return PCRE2_ERROR_NULL;++if ((options & ~PUBLIC_JIT_COMPILE_OPTIONS) != 0)+ return PCRE2_ERROR_JIT_BADOPTION;++/* Support for invalid UTF was first introduced in JIT, with the option+PCRE2_JIT_INVALID_UTF. Later, support was added to the interpreter, and the+compile-time option PCRE2_MATCH_INVALID_UTF was created. This is now the+preferred feature, with the earlier option deprecated. However, for backward+compatibility, if the earlier option is set, it forces the new option so that+if JIT matching falls back to the interpreter, there is still support for+invalid UTF. However, if this function has already been successfully called+without PCRE2_JIT_INVALID_UTF and without PCRE2_MATCH_INVALID_UTF (meaning that+non-invalid-supporting JIT code was compiled), give an error.++If in the future support for PCRE2_JIT_INVALID_UTF is withdrawn, the following+actions are needed:++ 1. Remove the definition from pcre2.h.in and from the list in+ PUBLIC_JIT_COMPILE_OPTIONS above.++ 2. Replace PCRE2_JIT_INVALID_UTF with a local flag in this module.++ 3. Replace PCRE2_JIT_INVALID_UTF in pcre2_jit_test.c.++ 4. Delete the following short block of code. The setting of "re" and+ "functions" can be moved into the JIT-only block below, but if that is+ done, (void)re and (void)functions will be needed in the non-JIT case, to+ avoid compiler warnings.+*/++#ifdef SUPPORT_JIT+executable_functions *functions = (executable_functions *)re->executable_jit;+static int executable_allocator_is_working = 0;+#endif++if ((options & PCRE2_JIT_INVALID_UTF) != 0)+ {+ if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) == 0)+ {+#ifdef SUPPORT_JIT+ if (functions != NULL) return PCRE2_ERROR_JIT_BADOPTION;+#endif+ re->overall_options |= PCRE2_MATCH_INVALID_UTF;+ }+ }++/* The above tests are run with and without JIT support. This means that+PCRE2_JIT_INVALID_UTF propagates back into the regex options (ensuring+interpreter support) even in the absence of JIT. But now, if there is no JIT+support, give an error return. */++#ifndef SUPPORT_JIT+return PCRE2_ERROR_JIT_BADOPTION;+#else /* SUPPORT_JIT */++/* There is JIT support. Do the necessary. */++if ((re->flags & PCRE2_NOJIT) != 0) return 0;++if (executable_allocator_is_working == 0)+ {+ /* Checks whether the executable allocator is working. This check+ might run multiple times in multi-threaded environments, but the+ result should not be affected by it. */+ void *ptr = SLJIT_MALLOC_EXEC(32, NULL);++ executable_allocator_is_working = -1;++ if (ptr != NULL)+ {+ SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr), NULL);+ executable_allocator_is_working = 1;+ }+ }++if (executable_allocator_is_working < 0)+ return PCRE2_ERROR_NOMEMORY;++if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0)+ options |= PCRE2_JIT_INVALID_UTF;++if ((options & PCRE2_JIT_COMPLETE) != 0 && (functions == NULL+ || functions->executable_funcs[0] == NULL)) {+ uint32_t excluded_options = (PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_PARTIAL_HARD);+ int result = jit_compile(code, options & ~excluded_options);+ if (result != 0)+ return result;+ }++if ((options & PCRE2_JIT_PARTIAL_SOFT) != 0 && (functions == NULL+ || functions->executable_funcs[1] == NULL)) {+ uint32_t excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_HARD);+ int result = jit_compile(code, options & ~excluded_options);+ if (result != 0)+ return result;+ }++if ((options & PCRE2_JIT_PARTIAL_HARD) != 0 && (functions == NULL+ || functions->executable_funcs[2] == NULL)) {+ uint32_t excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT);+ int result = jit_compile(code, options & ~excluded_options);+ if (result != 0)+ return result;+ }++return 0;++#endif /* SUPPORT_JIT */+}++/* JIT compiler uses an all-in-one approach. This improves security,+ since the code generator functions are not exported. */++#define INCLUDED_FROM_PCRE2_JIT_COMPILE++#include "pcre2_jit_match.c"+#include "pcre2_jit_misc.c"++/* End of pcre2_jit_compile.c */
+ src/c/pcre2/src/pcre2_jit_match.c view
@@ -0,0 +1,186 @@+/*************************************************+* 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) 2016-2018 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.+-----------------------------------------------------------------------------+*/++#ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE+#error This file must be included from pcre2_jit_compile.c.+#endif++#ifdef SUPPORT_JIT++static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, jit_function executable_func)+{+sljit_u8 local_space[MACHINE_STACK_SIZE];+struct sljit_stack local_stack;++local_stack.min_start = local_space;+local_stack.start = local_space;+local_stack.end = local_space + MACHINE_STACK_SIZE;+local_stack.top = local_space + MACHINE_STACK_SIZE;+arguments->stack = &local_stack;+return executable_func(arguments);+}++#endif+++/*************************************************+* Do a JIT pattern match *+*************************************************/++/* This function runs a JIT pattern match.++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 to a match context++Returns: > 0 => success; value is the number of ovector pairs filled+ = 0 => success, but ovector is not big enough+ -1 => failed to match (PCRE_ERROR_NOMATCH)+ < -1 => some kind of unexpected problem+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_jit_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)+{+#ifndef SUPPORT_JIT++(void)code;+(void)subject;+(void)length;+(void)start_offset;+(void)options;+(void)match_data;+(void)mcontext;+return PCRE2_ERROR_JIT_BADOPTION;++#else /* SUPPORT_JIT */++pcre2_real_code *re = (pcre2_real_code *)code;+executable_functions *functions = (executable_functions *)re->executable_jit;+pcre2_jit_stack *jit_stack;+uint32_t oveccount = match_data->oveccount;+uint32_t max_oveccount;+union {+ void *executable_func;+ jit_function call_executable_func;+} convert_executable_func;+jit_arguments arguments;+int rc;+int index = 0;++if ((options & PCRE2_PARTIAL_HARD) != 0)+ index = 2;+else if ((options & PCRE2_PARTIAL_SOFT) != 0)+ index = 1;++if (functions == NULL || functions->executable_funcs[index] == NULL)+ return PCRE2_ERROR_JIT_BADOPTION;++/* Sanity checks should be handled by pcre_exec. */+arguments.str = subject + start_offset;+arguments.begin = subject;+arguments.end = subject + length;+arguments.match_data = match_data;+arguments.startchar_ptr = subject;+arguments.mark_ptr = NULL;+arguments.options = options;++if (mcontext != NULL)+ {+ arguments.callout = mcontext->callout;+ arguments.callout_data = mcontext->callout_data;+ arguments.offset_limit = mcontext->offset_limit;+ arguments.limit_match = (mcontext->match_limit < re->limit_match)?+ mcontext->match_limit : re->limit_match;+ if (mcontext->jit_callback != NULL)+ jit_stack = mcontext->jit_callback(mcontext->jit_callback_data);+ else+ jit_stack = (pcre2_jit_stack *)mcontext->jit_callback_data;+ }+else+ {+ arguments.callout = NULL;+ arguments.callout_data = NULL;+ arguments.offset_limit = PCRE2_UNSET;+ arguments.limit_match = (MATCH_LIMIT < re->limit_match)?+ MATCH_LIMIT : re->limit_match;+ jit_stack = NULL;+ }+++max_oveccount = functions->top_bracket;+if (oveccount > max_oveccount)+ oveccount = max_oveccount;+arguments.oveccount = oveccount << 1;+++convert_executable_func.executable_func = functions->executable_funcs[index];+if (jit_stack != NULL)+ {+ arguments.stack = (struct sljit_stack *)(jit_stack->stack);+ rc = convert_executable_func.call_executable_func(&arguments);+ }+else+ rc = jit_machine_stack_exec(&arguments, convert_executable_func.call_executable_func);++if (rc > (int)oveccount)+ rc = 0;+match_data->code = re;+match_data->subject = (rc >= 0 || rc == PCRE2_ERROR_PARTIAL)? subject : NULL;+match_data->rc = rc;+match_data->startchar = arguments.startchar_ptr - subject;+match_data->leftchar = 0;+match_data->rightchar = 0;+match_data->mark = arguments.mark_ptr;+match_data->matchedby = PCRE2_MATCHEDBY_JIT;++return match_data->rc;++#endif /* SUPPORT_JIT */+}++/* End of pcre2_jit_match.c */
+ src/c/pcre2/src/pcre2_jit_misc.c view
@@ -0,0 +1,232 @@+/*************************************************+* 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) 2016 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.+-----------------------------------------------------------------------------+*/+++#ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE+#error This file must be included from pcre2_jit_compile.c.+#endif++++/*************************************************+* Free JIT read-only data *+*************************************************/++void+PRIV(jit_free_rodata)(void *current, void *allocator_data)+{+#ifndef SUPPORT_JIT+(void)current;+(void)allocator_data;+#else /* SUPPORT_JIT */+void *next;++SLJIT_UNUSED_ARG(allocator_data);++while (current != NULL)+ {+ next = *(void**)current;+ SLJIT_FREE(current, allocator_data);+ current = next;+ }++#endif /* SUPPORT_JIT */+}++/*************************************************+* Free JIT compiled code *+*************************************************/++void+PRIV(jit_free)(void *executable_jit, pcre2_memctl *memctl)+{+#ifndef SUPPORT_JIT+(void)executable_jit;+(void)memctl;+#else /* SUPPORT_JIT */++executable_functions *functions = (executable_functions *)executable_jit;+void *allocator_data = memctl;+int i;++for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)+ {+ if (functions->executable_funcs[i] != NULL)+ sljit_free_code(functions->executable_funcs[i], NULL);+ PRIV(jit_free_rodata)(functions->read_only_data_heads[i], allocator_data);+ }++SLJIT_FREE(functions, allocator_data);++#endif /* SUPPORT_JIT */+}+++/*************************************************+* Free unused JIT memory *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_jit_free_unused_memory(pcre2_general_context *gcontext)+{+#ifndef SUPPORT_JIT+(void)gcontext; /* Suppress warning */+#else /* SUPPORT_JIT */+SLJIT_UNUSED_ARG(gcontext);+sljit_free_unused_memory_exec();+#endif /* SUPPORT_JIT */+}++++/*************************************************+* Allocate a JIT stack *+*************************************************/++PCRE2_EXP_DEFN pcre2_jit_stack * PCRE2_CALL_CONVENTION+pcre2_jit_stack_create(size_t startsize, size_t maxsize,+ pcre2_general_context *gcontext)+{+#ifndef SUPPORT_JIT++(void)gcontext;+(void)startsize;+(void)maxsize;+return NULL;++#else /* SUPPORT_JIT */++pcre2_jit_stack *jit_stack;++if (startsize < 1 || maxsize < 1)+ return NULL;+if (startsize > maxsize)+ startsize = maxsize;+startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);+maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);++jit_stack = PRIV(memctl_malloc)(sizeof(pcre2_real_jit_stack), (pcre2_memctl *)gcontext);+if (jit_stack == NULL) return NULL;+jit_stack->stack = sljit_allocate_stack(startsize, maxsize, &jit_stack->memctl);+if (jit_stack->stack == NULL)+ {+ jit_stack->memctl.free(jit_stack, jit_stack->memctl.memory_data);+ return NULL;+ }+return jit_stack;++#endif+}+++/*************************************************+* Assign a JIT stack to a pattern *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_jit_stack_assign(pcre2_match_context *mcontext, pcre2_jit_callback callback,+ void *callback_data)+{+#ifndef SUPPORT_JIT+(void)mcontext;+(void)callback;+(void)callback_data;+#else /* SUPPORT_JIT */++if (mcontext == NULL) return;+mcontext->jit_callback = callback;+mcontext->jit_callback_data = callback_data;++#endif /* SUPPORT_JIT */+}+++/*************************************************+* Free a JIT stack *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_jit_stack_free(pcre2_jit_stack *jit_stack)+{+#ifndef SUPPORT_JIT+(void)jit_stack;+#else /* SUPPORT_JIT */+if (jit_stack != NULL)+ {+ sljit_free_stack((struct sljit_stack *)(jit_stack->stack), &jit_stack->memctl);+ jit_stack->memctl.free(jit_stack, jit_stack->memctl.memory_data);+ }+#endif /* SUPPORT_JIT */+}+++/*************************************************+* Get target CPU type *+*************************************************/++const char*+PRIV(jit_get_target)(void)+{+#ifndef SUPPORT_JIT+return "JIT is not supported";+#else /* SUPPORT_JIT */+return sljit_get_platform_name();+#endif /* SUPPORT_JIT */+}+++/*************************************************+* Get size of JIT code *+*************************************************/++size_t+PRIV(jit_get_size)(void *executable_jit)+{+#ifndef SUPPORT_JIT+(void)executable_jit;+return 0;+#else /* SUPPORT_JIT */+sljit_uw *executable_sizes = ((executable_functions *)executable_jit)->executable_sizes;+SLJIT_COMPILE_ASSERT(JIT_NUMBER_OF_COMPILE_MODES == 3, number_of_compile_modes_changed);+return executable_sizes[0] + executable_sizes[1] + executable_sizes[2];+#endif+}++/* End of pcre2_jit_misc.c */
+ src/c/pcre2/src/pcre2_jit_neon_inc.h view
@@ -0,0 +1,343 @@+/*************************************************+* 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+ This module by Zoltan Herczeg and Sebastian Pop+ Original API code Copyright (c) 1997-2012 University of Cambridge+ New API code Copyright (c) 2016-2019 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.+-----------------------------------------------------------------------------+*/++# if defined(FFCS)+# if defined(FF_UTF)+# define FF_FUN ffcs_utf+# else+# define FF_FUN ffcs+# endif++# elif defined(FFCS_2)+# if defined(FF_UTF)+# define FF_FUN ffcs_2_utf+# else+# define FF_FUN ffcs_2+# endif++# elif defined(FFCS_MASK)+# if defined(FF_UTF)+# define FF_FUN ffcs_mask_utf+# else+# define FF_FUN ffcs_mask+# endif++# elif defined(FFCPS_0)+# if defined (FF_UTF)+# define FF_FUN ffcps_0_utf+# else+# define FF_FUN ffcps_0+# endif++# elif defined (FFCPS_1)+# if defined (FF_UTF)+# define FF_FUN ffcps_1_utf+# else+# define FF_FUN ffcps_1+# endif++# elif defined (FFCPS_DEFAULT)+# if defined (FF_UTF)+# define FF_FUN ffcps_default_utf+# else+# define FF_FUN ffcps_default+# endif+# endif++static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 *str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)+#undef FF_FUN+{+quad_word qw;+int_char ic;+ic.x = chars;++#if defined(FFCS)+sljit_u8 c1 = ic.c.c1;+vect_t vc1 = VDUPQ(c1);++#elif defined(FFCS_2)+sljit_u8 c1 = ic.c.c1;+vect_t vc1 = VDUPQ(c1);+sljit_u8 c2 = ic.c.c2;+vect_t vc2 = VDUPQ(c2);++#elif defined(FFCS_MASK)+sljit_u8 c1 = ic.c.c1;+vect_t vc1 = VDUPQ(c1);+sljit_u8 mask = ic.c.c2;+vect_t vmask = VDUPQ(mask);+#endif++#if defined(FFCPS)+compare_type compare1_type = compare_match1;+compare_type compare2_type = compare_match1;+vect_t cmp1a, cmp1b, cmp2a, cmp2b;+const sljit_u32 diff = IN_UCHARS(offs1 - offs2);+PCRE2_UCHAR char1a = ic.c.c1;+PCRE2_UCHAR char2a = ic.c.c3;++# ifdef FFCPS_CHAR1A2A+cmp1a = VDUPQ(char1a);+cmp2a = VDUPQ(char2a);+cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */+cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */+# else+PCRE2_UCHAR char1b = ic.c.c2;+PCRE2_UCHAR char2b = ic.c.c4;+if (char1a == char1b)+ {+ cmp1a = VDUPQ(char1a);+ cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */+ }+else+ {+ sljit_u32 bit1 = char1a ^ char1b;+ if (is_powerof2(bit1))+ {+ compare1_type = compare_match1i;+ cmp1a = VDUPQ(char1a | bit1);+ cmp1b = VDUPQ(bit1);+ }+ else+ {+ compare1_type = compare_match2;+ cmp1a = VDUPQ(char1a);+ cmp1b = VDUPQ(char1b);+ }+ }++if (char2a == char2b)+ {+ cmp2a = VDUPQ(char2a);+ cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */+ }+else+ {+ sljit_u32 bit2 = char2a ^ char2b;+ if (is_powerof2(bit2))+ {+ compare2_type = compare_match1i;+ cmp2a = VDUPQ(char2a | bit2);+ cmp2b = VDUPQ(bit2);+ }+ else+ {+ compare2_type = compare_match2;+ cmp2a = VDUPQ(char2a);+ cmp2b = VDUPQ(char2b);+ }+ }+# endif++str_ptr += IN_UCHARS(offs1);+#endif++#if PCRE2_CODE_UNIT_WIDTH != 8+vect_t char_mask = VDUPQ(0xff);+#endif++#if defined(FF_UTF)+restart:;+#endif++#if defined(FFCPS)+sljit_u8 *p1 = str_ptr - diff;+#endif+sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);+str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);+vect_t data = VLD1Q(str_ptr);+#if PCRE2_CODE_UNIT_WIDTH != 8+data = VANDQ(data, char_mask);+#endif+ +#if defined(FFCS)+vect_t eq = VCEQQ(data, vc1);++#elif defined(FFCS_2)+vect_t eq1 = VCEQQ(data, vc1);+vect_t eq2 = VCEQQ(data, vc2);+vect_t eq = VORRQ(eq1, eq2); ++#elif defined(FFCS_MASK)+vect_t eq = VORRQ(data, vmask);+eq = VCEQQ(eq, vc1);++#elif defined(FFCPS)+# if defined(FFCPS_DIFF1)+vect_t prev_data = data;+# endif++vect_t data2;+if (p1 < str_ptr)+ {+ data2 = VLD1Q(str_ptr - diff);+#if PCRE2_CODE_UNIT_WIDTH != 8+ data2 = VANDQ(data2, char_mask);+#endif+ }+else+ data2 = shift_left_n_lanes(data, offs1 - offs2);+ +if (compare1_type == compare_match1)+ data = VCEQQ(data, cmp1a);+else+ data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);++if (compare2_type == compare_match1)+ data2 = VCEQQ(data2, cmp2a);+else+ data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);++vect_t eq = VANDQ(data, data2);+#endif++VST1Q(qw.mem, eq);+/* Ignore matches before the first STR_PTR. */+if (align_offset < 8)+ {+ qw.dw[0] >>= align_offset * 8;+ if (qw.dw[0])+ {+ str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;+ goto match;+ }+ if (qw.dw[1])+ {+ str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;+ goto match;+ }+ }+else+ {+ qw.dw[1] >>= (align_offset - 8) * 8;+ if (qw.dw[1])+ {+ str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;+ goto match;+ }+ }+str_ptr += 16;++while (str_ptr < str_end)+ {+ vect_t orig_data = VLD1Q(str_ptr);+#if PCRE2_CODE_UNIT_WIDTH != 8+ orig_data = VANDQ(orig_data, char_mask);+#endif+ data = orig_data;++#if defined(FFCS)+ eq = VCEQQ(data, vc1);++#elif defined(FFCS_2)+ eq1 = VCEQQ(data, vc1);+ eq2 = VCEQQ(data, vc2);+ eq = VORRQ(eq1, eq2); ++#elif defined(FFCS_MASK)+ eq = VORRQ(data, vmask);+ eq = VCEQQ(eq, vc1);+#endif++#if defined(FFCPS)+# if defined (FFCPS_DIFF1)+ data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);+# else+ data2 = VLD1Q(str_ptr - diff);+# if PCRE2_CODE_UNIT_WIDTH != 8+ data2 = VANDQ(data2, char_mask);+# endif+# endif++# ifdef FFCPS_CHAR1A2A+ data = VCEQQ(data, cmp1a);+ data2 = VCEQQ(data2, cmp2a);+# else+ if (compare1_type == compare_match1)+ data = VCEQQ(data, cmp1a);+ else+ data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);+ if (compare2_type == compare_match1)+ data2 = VCEQQ(data2, cmp2a);+ else+ data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);+# endif++ eq = VANDQ(data, data2);+#endif++ VST1Q(qw.mem, eq);+ if (qw.dw[0])+ str_ptr += __builtin_ctzll(qw.dw[0]) / 8;+ else if (qw.dw[1])+ str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;+ else {+ str_ptr += 16;+#if defined (FFCPS_DIFF1)+ prev_data = orig_data;+#endif+ continue;+ }++match:;+ if (str_ptr >= str_end)+ /* Failed match. */+ return NULL;++#if defined(FF_UTF)+ if (utf_continue(str_ptr + IN_UCHARS(-offs1)))+ {+ /* Not a match. */+ str_ptr += IN_UCHARS(1);+ goto restart;+ }+#endif++ /* Match. */+#if defined (FFCPS)+ str_ptr -= IN_UCHARS(offs1);+#endif+ return str_ptr;+ }++/* Failed match. */+return NULL;+}
+ src/c/pcre2/src/pcre2_jit_simd_inc.h view
@@ -0,0 +1,1123 @@+/*************************************************+* 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+ This module by Zoltan Herczeg+ Original API code Copyright (c) 1997-2012 University of Cambridge+ New API code Copyright (c) 2016-2019 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.+-----------------------------------------------------------------------------+*/++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+static struct sljit_jump *jump_if_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);+return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0x80);+#elif PCRE2_CODE_UNIT_WIDTH == 16+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);+return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00);+#else+#error "Unknown code width"+#endif+}+#endif++static sljit_s32 character_to_int32(PCRE2_UCHAR chr)+{+sljit_u32 value = chr;+#if PCRE2_CODE_UNIT_WIDTH == 8+#define SSE2_COMPARE_TYPE_INDEX 0+return (sljit_s32)((value << 24) | (value << 16) | (value << 8) | value);+#elif PCRE2_CODE_UNIT_WIDTH == 16+#define SSE2_COMPARE_TYPE_INDEX 1+return (sljit_s32)((value << 16) | value);+#elif PCRE2_CODE_UNIT_WIDTH == 32+#define SSE2_COMPARE_TYPE_INDEX 2+return (sljit_s32)(value);+#else+#error "Unsupported unit width"+#endif+}++static void load_from_mem_sse2(struct sljit_compiler *compiler, sljit_s32 dst_xmm_reg, sljit_s32 src_general_reg, sljit_s8 offset)+{+sljit_u8 instruction[5];++SLJIT_ASSERT(dst_xmm_reg < 8);+SLJIT_ASSERT(src_general_reg < 8);++/* MOVDQA xmm1, xmm2/m128 */+instruction[0] = ((sljit_u8)offset & 0xf) == 0 ? 0x66 : 0xf3;+instruction[1] = 0x0f;+instruction[2] = 0x6f;++if (offset == 0)+ {+ instruction[3] = (dst_xmm_reg << 3) | src_general_reg;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;+ }++instruction[3] = 0x40 | (dst_xmm_reg << 3) | src_general_reg;+instruction[4] = (sljit_u8)offset;+sljit_emit_op_custom(compiler, instruction, 5);+}++typedef enum {+ sse2_compare_match1,+ sse2_compare_match1i,+ sse2_compare_match2,+} sse2_compare_type;++static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, sse2_compare_type compare_type,+ int step, sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind)+{+sljit_u8 instruction[4];+instruction[0] = 0x66;+instruction[1] = 0x0f;++SLJIT_ASSERT(step >= 0 && step <= 3);++if (compare_type != sse2_compare_match2)+ {+ if (step == 0)+ {+ if (compare_type == sse2_compare_match1i)+ {+ /* POR xmm1, xmm2/m128 */+ /* instruction[0] = 0x66; */+ /* instruction[1] = 0x0f; */+ instruction[2] = 0xeb;+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp2_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ }+ return;+ }++ if (step != 2)+ return;++ /* PCMPEQB/W/D xmm1, xmm2/m128 */+ /* instruction[0] = 0x66; */+ /* instruction[1] = 0x0f; */+ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;+ }++switch (step)+ {+ case 0:+ /* MOVDQA xmm1, xmm2/m128 */+ /* instruction[0] = 0x66; */+ /* instruction[1] = 0x0f; */+ instruction[2] = 0x6f;+ instruction[3] = 0xc0 | (tmp_ind << 3) | dst_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;++ case 1:+ /* PCMPEQB/W/D xmm1, xmm2/m128 */+ /* instruction[0] = 0x66; */+ /* instruction[1] = 0x0f; */+ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;++ case 2:+ /* PCMPEQB/W/D xmm1, xmm2/m128 */+ /* instruction[0] = 0x66; */+ /* instruction[1] = 0x0f; */+ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;+ instruction[3] = 0xc0 | (tmp_ind << 3) | cmp2_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;++ case 3:+ /* POR xmm1, xmm2/m128 */+ /* instruction[0] = 0x66; */+ /* instruction[1] = 0x0f; */+ instruction[2] = 0xeb;+ instruction[3] = 0xc0 | (dst_ind << 3) | tmp_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ return;+ }+}++#define JIT_HAS_FAST_FORWARD_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))++static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)+{+DEFINE_COMPILER;+struct sljit_label *start;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_label *restart;+#endif+struct sljit_jump *quit;+struct sljit_jump *partial_quit[2];+sse2_compare_type compare_type = sse2_compare_match1;+sljit_u8 instruction[8];+sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);+sljit_s32 data_ind = 0;+sljit_s32 tmp_ind = 1;+sljit_s32 cmp1_ind = 2;+sljit_s32 cmp2_ind = 3;+sljit_u32 bit = 0;+int i;++SLJIT_UNUSED_ARG(offset);++if (char1 != char2)+ {+ bit = char1 ^ char2;+ compare_type = sse2_compare_match1i;++ if (!is_powerof2(bit))+ {+ bit = 0;+ compare_type = sse2_compare_match2;+ }+ }++partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit[0]);++/* First part (unaligned start) */++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));++SLJIT_ASSERT(tmp1_reg_ind < 8);++/* MOVD xmm, r/m32 */+instruction[0] = 0x66;+instruction[1] = 0x0f;+instruction[2] = 0x6e;+instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_reg_ind;+sljit_emit_op_custom(compiler, instruction, 4);++if (char1 != char2)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));++ /* MOVD xmm, r/m32 */+ instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_reg_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ }++OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);++/* PSHUFD xmm1, xmm2/m128, imm8 */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0x70;+instruction[3] = 0xc0 | (cmp1_ind << 3) | cmp1_ind;+instruction[4] = 0;+sljit_emit_op_custom(compiler, instruction, 5);++if (char1 != char2)+ {+ /* PSHUFD xmm1, xmm2/m128, imm8 */+ instruction[3] = 0xc0 | (cmp2_ind << 3) | cmp2_ind;+ sljit_emit_op_custom(compiler, instruction, 5);+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+restart = LABEL();+#endif+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);++load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);+for (i = 0; i < 4; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* PMOVMSKB reg, xmm */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0xd7;+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;+sljit_emit_op_custom(compiler, instruction, 4);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);++quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* Second part (aligned) */+start = LABEL();++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);++partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit[1]);++load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);+for (i = 0; i < 4; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* PMOVMSKB reg, xmm */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0xd7;+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;+sljit_emit_op_custom(compiler, instruction, 4);++CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(quit);++/* BSF r32, r/m32 */+instruction[0] = 0x0f;+instruction[1] = 0xbc;+instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;+sljit_emit_op_custom(compiler, instruction, 3);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);++if (common->mode != PCRE2_JIT_COMPLETE)+ {+ JUMPHERE(partial_quit[0]);+ JUMPHERE(partial_quit[1]);+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);+ CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);+ }+else+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && offset > 0)+ {+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));++ quit = jump_if_utf_char_start(compiler, TMP1);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));+ OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, restart);++ JUMPHERE(quit);+ }+#endif+}++#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))++static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2)+{+DEFINE_COMPILER;+struct sljit_label *start;+struct sljit_jump *quit;+jump_list *not_found = NULL;+sse2_compare_type compare_type = sse2_compare_match1;+sljit_u8 instruction[8];+sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);+sljit_s32 data_ind = 0;+sljit_s32 tmp_ind = 1;+sljit_s32 cmp1_ind = 2;+sljit_s32 cmp2_ind = 3;+sljit_u32 bit = 0;+int i;++if (char1 != char2)+ {+ bit = char1 ^ char2;+ compare_type = sse2_compare_match1i;++ if (!is_powerof2(bit))+ {+ bit = 0;+ compare_type = sse2_compare_match2;+ }+ }++add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));+OP1(SLJIT_MOV, TMP2, 0, TMP1, 0);+OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);++/* First part (unaligned start) */++OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));++SLJIT_ASSERT(tmp1_reg_ind < 8);++/* MOVD xmm, r/m32 */+instruction[0] = 0x66;+instruction[1] = 0x0f;+instruction[2] = 0x6e;+instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_reg_ind;+sljit_emit_op_custom(compiler, instruction, 4);++if (char1 != char2)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));++ /* MOVD xmm, r/m32 */+ instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_reg_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ }++OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);++/* PSHUFD xmm1, xmm2/m128, imm8 */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0x70;+instruction[3] = 0xc0 | (cmp1_ind << 3) | cmp1_ind;+instruction[4] = 0;+sljit_emit_op_custom(compiler, instruction, 5);++if (char1 != char2)+ {+ /* PSHUFD xmm1, xmm2/m128, imm8 */+ instruction[3] = 0xc0 | (cmp2_ind << 3) | cmp2_ind;+ sljit_emit_op_custom(compiler, instruction, 5);+ }++OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);++load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);+for (i = 0; i < 4; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* PMOVMSKB reg, xmm */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0xd7;+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;+sljit_emit_op_custom(compiler, instruction, 4);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);++quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* Second part (aligned) */+start = LABEL();++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);++add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);+for (i = 0; i < 4; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* PMOVMSKB reg, xmm */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0xd7;+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;+sljit_emit_op_custom(compiler, instruction, 4);++CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(quit);++/* BSF r32, r/m32 */+instruction[0] = 0x0f;+instruction[1] = 0xbc;+instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;+sljit_emit_op_custom(compiler, instruction, 3);++OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, STR_PTR, 0);+add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));++OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+return not_found;+}++#ifndef _WIN64++static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+return 15;+#elif PCRE2_CODE_UNIT_WIDTH == 16+return 7;+#elif PCRE2_CODE_UNIT_WIDTH == 32+return 3;+#else+#error "Unsupported unit width"+#endif+}++#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))++static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,+ PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)+{+DEFINE_COMPILER;+sse2_compare_type compare1_type = sse2_compare_match1;+sse2_compare_type compare2_type = sse2_compare_match1;+sljit_u32 bit1 = 0;+sljit_u32 bit2 = 0;+sljit_u32 diff = IN_UCHARS(offs1 - offs2);+sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);+sljit_s32 tmp2_reg_ind = sljit_get_register_index(TMP2);+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);+sljit_s32 data1_ind = 0;+sljit_s32 data2_ind = 1;+sljit_s32 tmp1_ind = 2;+sljit_s32 tmp2_ind = 3;+sljit_s32 cmp1a_ind = 4;+sljit_s32 cmp1b_ind = 5;+sljit_s32 cmp2a_ind = 6;+sljit_s32 cmp2b_ind = 7;+struct sljit_label *start;+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+struct sljit_label *restart;+#endif+struct sljit_jump *jump[2];+sljit_u8 instruction[8];+int i;++SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);+SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));+SLJIT_ASSERT(tmp1_reg_ind < 8 && tmp2_reg_ind == 1);++/* Initialize. */+if (common->match_end_ptr != 0)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));++ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);+ CMOV(SLJIT_LESS, STR_END, TMP1, 0);+ }++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++/* MOVD xmm, r/m32 */+instruction[0] = 0x66;+instruction[1] = 0x0f;+instruction[2] = 0x6e;++if (char1a == char1b)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));+else+ {+ bit1 = char1a ^ char1b;+ if (is_powerof2(bit1))+ {+ compare1_type = sse2_compare_match1i;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a | bit1));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit1));+ }+ else+ {+ compare1_type = sse2_compare_match2;+ bit1 = 0;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char1b));+ }+ }++instruction[3] = 0xc0 | (cmp1a_ind << 3) | tmp1_reg_ind;+sljit_emit_op_custom(compiler, instruction, 4);++if (char1a != char1b)+ {+ instruction[3] = 0xc0 | (cmp1b_ind << 3) | tmp2_reg_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ }++if (char2a == char2b)+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));+else+ {+ bit2 = char2a ^ char2b;+ if (is_powerof2(bit2))+ {+ compare2_type = sse2_compare_match1i;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a | bit2));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit2));+ }+ else+ {+ compare2_type = sse2_compare_match2;+ bit2 = 0;+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char2b));+ }+ }++instruction[3] = 0xc0 | (cmp2a_ind << 3) | tmp1_reg_ind;+sljit_emit_op_custom(compiler, instruction, 4);++if (char2a != char2b)+ {+ instruction[3] = 0xc0 | (cmp2b_ind << 3) | tmp2_reg_ind;+ sljit_emit_op_custom(compiler, instruction, 4);+ }++/* PSHUFD xmm1, xmm2/m128, imm8 */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0x70;+instruction[4] = 0;++instruction[3] = 0xc0 | (cmp1a_ind << 3) | cmp1a_ind;+sljit_emit_op_custom(compiler, instruction, 5);++if (char1a != char1b)+ {+ instruction[3] = 0xc0 | (cmp1b_ind << 3) | cmp1b_ind;+ sljit_emit_op_custom(compiler, instruction, 5);+ }++instruction[3] = 0xc0 | (cmp2a_ind << 3) | cmp2a_ind;+sljit_emit_op_custom(compiler, instruction, 5);++if (char2a != char2b)+ {+ instruction[3] = 0xc0 | (cmp2b_ind << 3) | cmp2b_ind;+ sljit_emit_op_custom(compiler, instruction, 5);+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+restart = LABEL();+#endif++OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, diff);+OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);++load_from_mem_sse2(compiler, data1_ind, str_ptr_reg_ind, 0);++jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_PTR, 0);++load_from_mem_sse2(compiler, data2_ind, str_ptr_reg_ind, -(sljit_s8)diff);+jump[1] = JUMP(SLJIT_JUMP);++JUMPHERE(jump[0]);++/* MOVDQA xmm1, xmm2/m128 */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0x6f;+instruction[3] = 0xc0 | (data2_ind << 3) | data1_ind;+sljit_emit_op_custom(compiler, instruction, 4);++/* PSLLDQ xmm1, imm8 */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0x73;+instruction[3] = 0xc0 | (7 << 3) | data2_ind;+instruction[4] = diff;+sljit_emit_op_custom(compiler, instruction, 5);++JUMPHERE(jump[1]);++OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);++for (i = 0; i < 4; i++)+ {+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);+ }++/* PAND xmm1, xmm2/m128 */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0xdb;+instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;+sljit_emit_op_custom(compiler, instruction, 4);++/* PMOVMSKB reg, xmm */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0xd7;+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | 0;+sljit_emit_op_custom(compiler, instruction, 4);++/* Ignore matches before the first STR_PTR. */+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);++jump[0] = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++/* Main loop. */+start = LABEL();++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++load_from_mem_sse2(compiler, data1_ind, str_ptr_reg_ind, 0);+load_from_mem_sse2(compiler, data2_ind, str_ptr_reg_ind, -(sljit_s8)diff);++for (i = 0; i < 4; i++)+ {+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp2_ind);+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp1_ind);+ }++/* PAND xmm1, xmm2/m128 */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0xdb;+instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;+sljit_emit_op_custom(compiler, instruction, 4);++/* PMOVMSKB reg, xmm */+/* instruction[0] = 0x66; */+/* instruction[1] = 0x0f; */+instruction[2] = 0xd7;+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | 0;+sljit_emit_op_custom(compiler, instruction, 4);++CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(jump[0]);++/* BSF r32, r/m32 */+instruction[0] = 0x0f;+instruction[1] = 0xbc;+instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;+sljit_emit_op_custom(compiler, instruction, 3);++OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);++add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));++ jump[0] = jump_if_utf_char_start(compiler, TMP1);++ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart);++ add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP));++ JUMPHERE(jump[0]);+ }+#endif++OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));++if (common->match_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);+}++#endif /* !_WIN64 */++#undef SSE2_COMPARE_TYPE_INDEX++#endif /* SLJIT_CONFIG_X86 && !SUPPORT_VALGRIND */++#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 && (defined __ARM_NEON || defined __ARM_NEON__))++#include <arm_neon.h>++typedef union {+ unsigned int x;+ struct { unsigned char c1, c2, c3, c4; } c;+} int_char;++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+static SLJIT_INLINE int utf_continue(sljit_u8 *s)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+return (*s & 0xc0) == 0x80;+#elif PCRE2_CODE_UNIT_WIDTH == 16+return (*s & 0xfc00) == 0xdc00;+#else+#error "Unknown code width"+#endif+}+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */++#if PCRE2_CODE_UNIT_WIDTH == 8+# define VECTOR_FACTOR 16+# define vect_t uint8x16_t+# define VLD1Q(X) vld1q_u8((sljit_u8 *)(X))+# define VCEQQ vceqq_u8+# define VORRQ vorrq_u8+# define VST1Q vst1q_u8+# define VDUPQ vdupq_n_u8+# define VEXTQ vextq_u8+# define VANDQ vandq_u8+typedef union {+ uint8_t mem[16];+ uint64_t dw[2];+} quad_word;+#elif PCRE2_CODE_UNIT_WIDTH == 16+# define VECTOR_FACTOR 8+# define vect_t uint16x8_t+# define VLD1Q(X) vld1q_u16((sljit_u16 *)(X))+# define VCEQQ vceqq_u16+# define VORRQ vorrq_u16+# define VST1Q vst1q_u16+# define VDUPQ vdupq_n_u16+# define VEXTQ vextq_u16+# define VANDQ vandq_u16+typedef union {+ uint16_t mem[8];+ uint64_t dw[2];+} quad_word;+#else+# define VECTOR_FACTOR 4+# define vect_t uint32x4_t+# define VLD1Q(X) vld1q_u32((sljit_u32 *)(X))+# define VCEQQ vceqq_u32+# define VORRQ vorrq_u32+# define VST1Q vst1q_u32+# define VDUPQ vdupq_n_u32+# define VEXTQ vextq_u32+# define VANDQ vandq_u32+typedef union {+ uint32_t mem[4];+ uint64_t dw[2];+} quad_word;+#endif++#define FFCS+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCS++#define FFCS_2+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCS_2++#define FFCS_MASK+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCS_MASK++#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1++static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)+{+DEFINE_COMPILER;+int_char ic;+struct sljit_jump *partial_quit;+/* Save temporary registers. */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP3, 0);++/* Prepare function arguments */+OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);+OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0);+OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, offset);++if (char1 == char2)+ {+ ic.c.c1 = char1;+ ic.c.c2 = char2;+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf && offset > 0)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_utf));+ else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs));+#else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs));+#endif+ }+else+ {+ PCRE2_UCHAR mask = char1 ^ char2;+ if (is_powerof2(mask))+ {+ ic.c.c1 = char1 | mask;+ ic.c.c2 = mask;+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf && offset > 0)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask_utf));+ else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask));+#else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask));+#endif+ }+ else+ {+ ic.c.c1 = char1;+ ic.c.c2 = char2;+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf && offset > 0)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2_utf));+ else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2));+#else+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2));+#endif+ }+ }+/* Restore registers. */+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);++/* Check return value. */+partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+if (common->mode == PCRE2_JIT_COMPLETE)+ add_jump(compiler, &common->failed_match, partial_quit);++/* Fast forward STR_PTR to the result of memchr. */+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);++if (common->mode != PCRE2_JIT_COMPLETE)+ JUMPHERE(partial_quit);+}++typedef enum {+ compare_match1,+ compare_match1i,+ compare_match2,+} compare_type;++static inline vect_t fast_forward_char_pair_compare(compare_type ctype, vect_t dst, vect_t cmp1, vect_t cmp2)+{+if (ctype == compare_match2)+ {+ vect_t tmp = dst;+ dst = VCEQQ(dst, cmp1);+ tmp = VCEQQ(tmp, cmp2);+ dst = VORRQ(dst, tmp);+ return dst;+ }++if (ctype == compare_match1i)+ dst = VORRQ(dst, cmp2);+dst = VCEQQ(dst, cmp1);+return dst;+}++static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)+{+#if PCRE2_CODE_UNIT_WIDTH == 8+return 15;+#elif PCRE2_CODE_UNIT_WIDTH == 16+return 7;+#elif PCRE2_CODE_UNIT_WIDTH == 32+return 3;+#else+#error "Unsupported unit width"+#endif+}++/* ARM doesn't have a shift left across lanes. */+static SLJIT_INLINE vect_t shift_left_n_lanes(vect_t a, sljit_u8 n)+{+vect_t zero = VDUPQ(0);+SLJIT_ASSERT(0 < n && n < VECTOR_FACTOR);+/* VEXTQ takes an immediate as last argument. */+#define C(X) case X: return VEXTQ(zero, a, VECTOR_FACTOR - X);+switch (n)+ {+ C(1); C(2); C(3);+#if PCRE2_CODE_UNIT_WIDTH != 32+ C(4); C(5); C(6); C(7);+# if PCRE2_CODE_UNIT_WIDTH != 16+ C(8); C(9); C(10); C(11); C(12); C(13); C(14); C(15);+# endif+#endif+ default:+ /* Based on the ASSERT(0 < n && n < VECTOR_FACTOR) above, this won't+ happen. The return is still here for compilers to not warn. */+ return a;+ }+}++#define FFCPS+#define FFCPS_DIFF1+#define FFCPS_CHAR1A2A++#define FFCPS_0+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCPS_0++#undef FFCPS_CHAR1A2A++#define FFCPS_1+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCPS_1++#undef FFCPS_DIFF1++#define FFCPS_DEFAULT+#include "pcre2_jit_neon_inc.h"+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+# define FF_UTF+# include "pcre2_jit_neon_inc.h"+# undef FF_UTF+#endif+#undef FFCPS++#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD 1++static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,+ PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)+{+DEFINE_COMPILER;+sljit_u32 diff = IN_UCHARS(offs1 - offs2);+struct sljit_jump *partial_quit;+int_char ic;+SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);+SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));+SLJIT_ASSERT(compiler->scratches == 5);++/* Save temporary register STR_PTR. */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);++/* Prepare arguments for the function call. */+if (common->match_end_ptr == 0)+ OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);+else+ {+ OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);+ OP2(SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));++ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, STR_END, 0, SLJIT_R0, 0);+ CMOV(SLJIT_LESS, SLJIT_R0, STR_END, 0);+ }++OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0); +OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_IMM, offs1);+OP1(SLJIT_MOV_S32, SLJIT_R3, 0, SLJIT_IMM, offs2);+ic.c.c1 = char1a;+ic.c.c2 = char1b;+ic.c.c3 = char2a;+ic.c.c4 = char2b;+OP1(SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_IMM, ic.x);++if (diff == 1) {+ if (char1a == char1b && char2a == char2b) {+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_0_utf));+ else+#endif+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_0));+ } else {+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_1_utf));+ else+#endif+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_1));+ }+} else {+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_default_utf));+ else+#endif+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_default));+}++/* Restore STR_PTR register. */+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);++/* Check return value. */+partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+add_jump(compiler, &common->failed_match, partial_quit);++/* Fast forward STR_PTR to the result of memchr. */+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);++JUMPHERE(partial_quit);+}++#endif /* SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 */
+ src/c/pcre2/src/pcre2_jit_test.c view
@@ -0,0 +1,2501 @@+/*************************************************+* 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) 2016 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++#include <stdio.h>+#include <string.h>++#define PCRE2_CODE_UNIT_WIDTH 0+#include "pcre2.h"++/*+ Letter characters:+ \xe6\x92\xad = 0x64ad = 25773 (kanji)+ Non-letter characters:+ \xc2\xa1 = 0xa1 = (Inverted Exclamation Mark)+ \xf3\xa9\xb7\x80 = 0xe9dc0 = 957888+ \xed\xa0\x80 = 55296 = 0xd800 (Invalid UTF character)+ \xed\xb0\x80 = 56320 = 0xdc00 (Invalid UTF character)+ Newlines:+ \xc2\x85 = 0x85 = 133 (NExt Line = NEL)+ \xe2\x80\xa8 = 0x2028 = 8232 (Line Separator)+ Othercase pairs:+ \xc3\xa9 = 0xe9 = 233 (e')+ \xc3\x89 = 0xc9 = 201 (E')+ \xc3\xa1 = 0xe1 = 225 (a')+ \xc3\x81 = 0xc1 = 193 (A')+ \x53 = 0x53 = S+ \x73 = 0x73 = s+ \xc5\xbf = 0x17f = 383 (long S)+ \xc8\xba = 0x23a = 570+ \xe2\xb1\xa5 = 0x2c65 = 11365+ \xe1\xbd\xb8 = 0x1f78 = 8056+ \xe1\xbf\xb8 = 0x1ff8 = 8184+ \xf0\x90\x90\x80 = 0x10400 = 66560+ \xf0\x90\x90\xa8 = 0x10428 = 66600+ \xc7\x84 = 0x1c4 = 452+ \xc7\x85 = 0x1c5 = 453+ \xc7\x86 = 0x1c6 = 454+ Caseless sets:+ ucp_Armenian - \x{531}-\x{556} -> \x{561}-\x{586}+ ucp_Coptic - \x{2c80}-\x{2ce3} -> caseless: XOR 0x1+ ucp_Latin - \x{ff21}-\x{ff3a} -> \x{ff41]-\x{ff5a}++ Mark property:+ \xcc\x8d = 0x30d = 781+ Special:+ \xc2\x80 = 0x80 = 128 (lowest 2 byte character)+ \xdf\xbf = 0x7ff = 2047 (highest 2 byte character)+ \xe0\xa0\x80 = 0x800 = 2048 (lowest 2 byte character)+ \xef\xbf\xbf = 0xffff = 65535 (highest 3 byte character)+ \xf0\x90\x80\x80 = 0x10000 = 65536 (lowest 4 byte character)+ \xf4\x8f\xbf\xbf = 0x10ffff = 1114111 (highest allowed utf character)+*/++static int regression_tests(void);+static int invalid_utf8_regression_tests(void);+static int invalid_utf16_regression_tests(void);+static int invalid_utf32_regression_tests(void);++int main(void)+{+ int jit = 0;+#if defined SUPPORT_PCRE2_8+ pcre2_config_8(PCRE2_CONFIG_JIT, &jit);+#elif defined SUPPORT_PCRE2_16+ pcre2_config_16(PCRE2_CONFIG_JIT, &jit);+#elif defined SUPPORT_PCRE2_32+ pcre2_config_32(PCRE2_CONFIG_JIT, &jit);+#endif+ if (!jit) {+ printf("JIT must be enabled to run pcre_jit_test\n");+ return 1;+ }+ return regression_tests()+ | invalid_utf8_regression_tests()+ | invalid_utf16_regression_tests()+ | invalid_utf32_regression_tests();+}++/* --------------------------------------------------------------------------------------- */++#if !(defined SUPPORT_PCRE2_8) && !(defined SUPPORT_PCRE2_16) && !(defined SUPPORT_PCRE2_32)+#error SUPPORT_PCRE2_8 or SUPPORT_PCRE2_16 or SUPPORT_PCRE2_32 must be defined+#endif++#define MU (PCRE2_MULTILINE | PCRE2_UTF)+#define MUP (PCRE2_MULTILINE | PCRE2_UTF | PCRE2_UCP)+#define CMU (PCRE2_CASELESS | PCRE2_MULTILINE | PCRE2_UTF)+#define CMUP (PCRE2_CASELESS | PCRE2_MULTILINE | PCRE2_UTF | PCRE2_UCP)+#define M (PCRE2_MULTILINE)+#define MP (PCRE2_MULTILINE | PCRE2_UCP)+#define U (PCRE2_UTF)+#define CM (PCRE2_CASELESS | PCRE2_MULTILINE)++#define BSR(x) ((x) << 16)+#define A PCRE2_NEWLINE_ANYCRLF++#define GET_NEWLINE(x) ((x) & 0xffff)+#define GET_BSR(x) ((x) >> 16)++#define OFFSET_MASK 0x00ffff+#define F_NO8 0x010000+#define F_NO16 0x020000+#define F_NO32 0x020000+#define F_NOMATCH 0x040000+#define F_DIFF 0x080000+#define F_FORCECONV 0x100000+#define F_PROPERTY 0x200000++struct regression_test_case {+ int compile_options;+ int newline;+ int match_options;+ int start_offset;+ const char *pattern;+ const char *input;+};++static struct regression_test_case regression_test_cases[] = {+ /* Constant strings. */+ { MU, A, 0, 0, "AbC", "AbAbC" },+ { MU, A, 0, 0, "ACCEPT", "AACACCACCEACCEPACCEPTACCEPTT" },+ { CMU, A, 0, 0, "aA#\xc3\xa9\xc3\x81", "aA#Aa#\xc3\x89\xc3\xa1" },+ { M, A, 0, 0, "[^a]", "aAbB" },+ { CM, A, 0, 0, "[^m]", "mMnN" },+ { M, A, 0, 0, "a[^b][^#]", "abacd" },+ { CM, A, 0, 0, "A[^B][^E]", "abacd" },+ { CMU, A, 0, 0, "[^x][^#]", "XxBll" },+ { MU, A, 0, 0, "[^a]", "aaa\xc3\xa1#Ab" },+ { CMU, A, 0, 0, "[^A]", "aA\xe6\x92\xad" },+ { MU, A, 0, 0, "\\W(\\W)?\\w", "\r\n+bc" },+ { MU, A, 0, 0, "\\W(\\W)?\\w", "\n\r+bc" },+ { MU, A, 0, 0, "\\W(\\W)?\\w", "\r\r+bc" },+ { MU, A, 0, 0, "\\W(\\W)?\\w", "\n\n+bc" },+ { MU, A, 0, 0, "[axd]", "sAXd" },+ { CMU, A, 0, 0, "[axd]", "sAXd" },+ { CMU, A, 0, 0 | F_NOMATCH, "[^axd]", "DxA" },+ { MU, A, 0, 0, "[a-dA-C]", "\xe6\x92\xad\xc3\xa9.B" },+ { MU, A, 0, 0, "[^a-dA-C]", "\xe6\x92\xad\xc3\xa9" },+ { CMU, A, 0, 0, "[^\xc3\xa9]", "\xc3\xa9\xc3\x89." },+ { MU, A, 0, 0, "[^\xc3\xa9]", "\xc3\xa9\xc3\x89." },+ { MU, A, 0, 0, "[^a]", "\xc2\x80[]" },+ { CMU, A, 0, 0, "\xf0\x90\x90\xa7", "\xf0\x90\x91\x8f" },+ { CM, A, 0, 0, "1a2b3c4", "1a2B3c51A2B3C4" },+ { PCRE2_CASELESS, 0, 0, 0, "\xff#a", "\xff#\xff\xfe##\xff#A" },+ { PCRE2_CASELESS, 0, 0, 0, "\xfe", "\xff\xfc#\xfe\xfe" },+ { PCRE2_CASELESS, 0, 0, 0, "a1", "Aa1" },+#ifndef NEVER_BACKSLASH_C+ { M, A, 0, 0, "\\Ca", "cda" },+ { CM, A, 0, 0, "\\Ca", "CDA" },+ { M, A, 0, 0 | F_NOMATCH, "\\Cx", "cda" },+ { CM, A, 0, 0 | F_NOMATCH, "\\Cx", "CDA" },+#endif /* !NEVER_BACKSLASH_C */+ { CMUP, A, 0, 0, "\xf0\x90\x90\x80\xf0\x90\x90\xa8", "\xf0\x90\x90\xa8\xf0\x90\x90\x80" },+ { CMUP, A, 0, 0, "\xf0\x90\x90\x80{2}", "\xf0\x90\x90\x80#\xf0\x90\x90\xa8\xf0\x90\x90\x80" },+ { CMUP, A, 0, 0, "\xf0\x90\x90\xa8{2}", "\xf0\x90\x90\x80#\xf0\x90\x90\xa8\xf0\x90\x90\x80" },+ { CMUP, A, 0, 0, "\xe1\xbd\xb8\xe1\xbf\xb8", "\xe1\xbf\xb8\xe1\xbd\xb8" },+ { M, A, 0, 0, "[3-57-9]", "5" },+ { PCRE2_AUTO_CALLOUT, A, 0, 0, "12345678901234567890123456789012345678901234567890123456789012345678901234567890",+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" },++ /* Assertions. */+ { MU, A, 0, 0, "\\b[^A]", "A_B#" },+ { M, A, 0, 0 | F_NOMATCH, "\\b\\W", "\n*" },+ { MU, A, 0, 0, "\\B[^,]\\b[^s]\\b", "#X" },+ { MP, A, 0, 0, "\\B", "_\xa1" },+ { MP, A, 0, 0 | F_PROPERTY, "\\b_\\b[,A]\\B", "_," },+ { MUP, A, 0, 0, "\\b", "\xe6\x92\xad!" },+ { MUP, A, 0, 0, "\\B", "_\xc2\xa1\xc3\xa1\xc2\x85" },+ { MUP, A, 0, 0, "\\b[^A]\\B[^c]\\b[^_]\\B", "_\xc3\xa1\xe2\x80\xa8" },+ { MUP, A, 0, 0, "\\b\\w+\\B", "\xc3\x89\xc2\xa1\xe6\x92\xad\xc3\x81\xc3\xa1" },+ { MU, A, 0, 0 | F_NOMATCH, "\\b.", "\xcd\xbe" },+ { CMUP, A, 0, 0, "\\By", "\xf0\x90\x90\xa8y" },+ { M, A, 0, 0 | F_NOMATCH, "\\R^", "\n" },+ { M, A, 0, 1 | F_NOMATCH, "^", "\n" },+ { 0, 0, 0, 0, "^ab", "ab" },+ { 0, 0, 0, 0 | F_NOMATCH, "^ab", "aab" },+ { M, PCRE2_NEWLINE_CRLF, 0, 0, "^a", "\r\raa\n\naa\r\naa" },+ { MU, A, 0, 0, "^-", "\xe2\x80\xa8--\xc2\x85-\r\n-" },+ { M, PCRE2_NEWLINE_ANY, 0, 0, "^-", "a--b--\x85--" },+ { MU, PCRE2_NEWLINE_ANY, 0, 0, "^-", "a--\xe2\x80\xa8--" },+ { MU, PCRE2_NEWLINE_ANY, 0, 0, "^-", "a--\xc2\x85--" },+ { 0, 0, 0, 0, "ab$", "ab" },+ { 0, 0, 0, 0 | F_NOMATCH, "ab$", "abab\n\n" },+ { PCRE2_DOLLAR_ENDONLY, 0, 0, 0 | F_NOMATCH, "ab$", "abab\r\n" },+ { M, PCRE2_NEWLINE_CRLF, 0, 0, "a$", "\r\raa\n\naa\r\naa" },+ { M, PCRE2_NEWLINE_ANY, 0, 0, "a$", "aaa" },+ { MU, PCRE2_NEWLINE_ANYCRLF, 0, 0, "#$", "#\xc2\x85###\r#" },+ { MU, PCRE2_NEWLINE_ANY, 0, 0, "#$", "#\xe2\x80\xa9" },+ { 0, PCRE2_NEWLINE_ANY, PCRE2_NOTBOL, 0 | F_NOMATCH, "^a", "aa\naa" },+ { M, PCRE2_NEWLINE_ANY, PCRE2_NOTBOL, 0, "^a", "aa\naa" },+ { 0, PCRE2_NEWLINE_ANY, PCRE2_NOTEOL, 0 | F_NOMATCH, "a$", "aa\naa" },+ { 0, PCRE2_NEWLINE_ANY, PCRE2_NOTEOL, 0 | F_NOMATCH, "a$", "aa\r\n" },+ { U | PCRE2_DOLLAR_ENDONLY, PCRE2_NEWLINE_ANY, 0, 0 | F_PROPERTY, "\\p{Any}{2,}$", "aa\r\n" },+ { M, PCRE2_NEWLINE_ANY, PCRE2_NOTEOL, 0, "a$", "aa\naa" },+ { 0, PCRE2_NEWLINE_CR, 0, 0, ".\\Z", "aaa" },+ { U, PCRE2_NEWLINE_CR, 0, 0, "a\\Z", "aaa\r" },+ { 0, PCRE2_NEWLINE_CR, 0, 0, ".\\Z", "aaa\n" },+ { 0, PCRE2_NEWLINE_CRLF, 0, 0, ".\\Z", "aaa\r" },+ { U, PCRE2_NEWLINE_CRLF, 0, 0, ".\\Z", "aaa\n" },+ { 0, PCRE2_NEWLINE_CRLF, 0, 0, ".\\Z", "aaa\r\n" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\r" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\n" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\r\n" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\xe2\x80\xa8" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\r" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\n" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\r\n" },+ { U, PCRE2_NEWLINE_ANY, 0, 0, ".\\Z", "aaa\xc2\x85" },+ { U, PCRE2_NEWLINE_ANY, 0, 0, ".\\Z", "aaa\xe2\x80\xa8" },+ { M, A, 0, 0, "\\Aa", "aaa" },+ { M, A, 0, 1 | F_NOMATCH, "\\Aa", "aaa" },+ { M, A, 0, 1, "\\Ga", "aaa" },+ { M, A, 0, 1 | F_NOMATCH, "\\Ga", "aba" },+ { M, A, 0, 0, "a\\z", "aaa" },+ { M, A, 0, 0 | F_NOMATCH, "a\\z", "aab" },++ /* Brackets and alternatives. */+ { MU, A, 0, 0, "(ab|bb|cd)", "bacde" },+ { MU, A, 0, 0, "(?:ab|a)(bc|c)", "ababc" },+ { MU, A, 0, 0, "((ab|(cc))|(bb)|(?:cd|efg))", "abac" },+ { CMU, A, 0, 0, "((aB|(Cc))|(bB)|(?:cd|EFg))", "AcCe" },+ { MU, A, 0, 0, "((ab|(cc))|(bb)|(?:cd|ebg))", "acebebg" },+ { MU, A, 0, 0, "(?:(a)|(?:b))(cc|(?:d|e))(a|b)k", "accabdbbccbk" },+ { MU, A, 0, 0, "\xc7\x82|\xc6\x82", "\xf1\x83\x82\x82\xc7\x82\xc7\x83" },+ { MU, A, 0, 0, "=\xc7\x82|#\xc6\x82", "\xf1\x83\x82\x82=\xc7\x82\xc7\x83" },+ { MU, A, 0, 0, "\xc7\x82\xc7\x83|\xc6\x82\xc6\x82", "\xf1\x83\x82\x82\xc7\x82\xc7\x83" },+ { MU, A, 0, 0, "\xc6\x82\xc6\x82|\xc7\x83\xc7\x83|\xc8\x84\xc8\x84", "\xf1\x83\x82\x82\xc8\x84\xc8\x84" },+ { U, A, 0, 0, "\xe1\x81\x80|\xe2\x82\x80|\xe4\x84\x80", "\xdf\xbf\xc2\x80\xe4\x84\x80" },+ { U, A, 0, 0, "(?:\xe1\x81\x80|\xe2\x82\x80|\xe4\x84\x80)#", "\xdf\xbf\xc2\x80#\xe4\x84\x80#" },+ { CM, A, 0, 0, "ab|cd", "CD" },+ { CM, A, 0, 0, "a1277|a1377|bX487", "bx487" },+ { CM, A, 0, 0, "a1277|a1377|bx487", "bX487" },++ /* Greedy and non-greedy ? operators. */+ { MU, A, 0, 0, "(?:a)?a", "laab" },+ { CMU, A, 0, 0, "(A)?A", "llaab" },+ { MU, A, 0, 0, "(a)?\?a", "aab" }, /* ?? is the prefix of trygraphs in GCC. */+ { MU, A, 0, 0, "(a)?a", "manm" },+ { CMU, A, 0, 0, "(a|b)?\?d((?:e)?)", "ABABdx" },+ { MU, A, 0, 0, "(a|b)?\?d((?:e)?)", "abcde" },+ { MU, A, 0, 0, "((?:ab)?\?g|b(?:g(nn|d)?\?)?)?\?(?:n)?m", "abgnbgnnbgdnmm" },++ /* Greedy and non-greedy + operators */+ { MU, A, 0, 0, "(aa)+aa", "aaaaaaa" },+ { MU, A, 0, 0, "(aa)+?aa", "aaaaaaa" },+ { MU, A, 0, 0, "(?:aba|ab|a)+l", "ababamababal" },+ { MU, A, 0, 0, "(?:aba|ab|a)+?l", "ababamababal" },+ { MU, A, 0, 0, "(a(?:bc|cb|b|c)+?|ss)+e", "accssabccbcacbccbbXaccssabccbcacbccbbe" },+ { MU, A, 0, 0, "(a(?:bc|cb|b|c)+|ss)+?e", "accssabccbcacbccbbXaccssabccbcacbccbbe" },+ { MU, A, 0, 0, "(?:(b(c)+?)+)?\?(?:(bc)+|(cb)+)+(?:m)+", "bccbcccbcbccbcbPbccbcccbcbccbcbmmn" },++ /* Greedy and non-greedy * operators */+ { CMU, A, 0, 0, "(?:AA)*AB", "aaaaaaamaaaaaaab" },+ { MU, A, 0, 0, "(?:aa)*?ab", "aaaaaaamaaaaaaab" },+ { MU, A, 0, 0, "(aa|ab)*ab", "aaabaaab" },+ { CMU, A, 0, 0, "(aa|Ab)*?aB", "aaabaaab" },+ { MU, A, 0, 0, "(a|b)*(?:a)*(?:b)*m", "abbbaaababanabbbaaababamm" },+ { MU, A, 0, 0, "(a|b)*?(?:a)*?(?:b)*?m", "abbbaaababanabbbaaababamm" },+ { M, A, 0, 0, "a(a(\\1*)a|(b)b+){0}a", "aa" },+ { M, A, 0, 0, "((?:a|)*){0}a", "a" },++ /* Combining ? + * operators */+ { MU, A, 0, 0, "((bm)+)?\?(?:a)*(bm)+n|((am)+?)?(?:a)+(am)*n", "bmbmabmamaaamambmaman" },+ { MU, A, 0, 0, "(((ab)?cd)*ef)+g", "abcdcdefcdefefmabcdcdefcdefefgg" },+ { MU, A, 0, 0, "(((ab)?\?cd)*?ef)+?g", "abcdcdefcdefefmabcdcdefcdefefgg" },+ { MU, A, 0, 0, "(?:(ab)?c|(?:ab)+?d)*g", "ababcdccababddg" },+ { MU, A, 0, 0, "(?:(?:ab)?\?c|(ab)+d)*?g", "ababcdccababddg" },++ /* Single character iterators. */+ { MU, A, 0, 0, "(a+aab)+aaaab", "aaaabcaaaabaabcaabcaaabaaaab" },+ { MU, A, 0, 0, "(a*a*aab)+x", "aaaaabaabaaabmaabx" },+ { MU, A, 0, 0, "(a*?(b|ab)a*?)+x", "aaaabcxbbaabaacbaaabaabax" },+ { MU, A, 0, 0, "(a+(ab|ad)a+)+x", "aaabaaaadaabaaabaaaadaaax" },+ { MU, A, 0, 0, "(a?(a)a?)+(aaa)", "abaaabaaaaaaaa" },+ { MU, A, 0, 0, "(a?\?(a)a?\?)+(b)", "aaaacaaacaacacbaaab" },+ { MU, A, 0, 0, "(a{0,4}(b))+d", "aaaaaabaabcaaaaabaaaaabd" },+ { MU, A, 0, 0, "(a{0,4}?[^b])+d+(a{0,4}[^b])d+", "aaaaadaaaacaadddaaddd" },+ { MU, A, 0, 0, "(ba{2})+c", "baabaaabacbaabaac" },+ { MU, A, 0, 0, "(a*+bc++)+", "aaabbcaaabcccab" },+ { MU, A, 0, 0, "(a?+[^b])+", "babaacacb" },+ { MU, A, 0, 0, "(a{0,3}+b)(a{0,3}+b)(a{0,3}+)[^c]", "abaabaaacbaabaaaac" },+ { CMU, A, 0, 0, "([a-c]+[d-f]+?)+?g", "aBdacdehAbDaFgA" },+ { CMU, A, 0, 0, "[c-f]+k", "DemmFke" },+ { MU, A, 0, 0, "([DGH]{0,4}M)+", "GGDGHDGMMHMDHHGHM" },+ { MU, A, 0, 0, "([a-c]{4,}s)+", "abasabbasbbaabsbba" },+ { CMU, A, 0, 0, "[ace]{3,7}", "AcbDAcEEcEd" },+ { CMU, A, 0, 0, "[ace]{3,7}?", "AcbDAcEEcEd" },+ { CMU, A, 0, 0, "[ace]{3,}", "AcbDAcEEcEd" },+ { CMU, A, 0, 0, "[ace]{3,}?", "AcbDAcEEcEd" },+ { MU, A, 0, 0, "[ckl]{2,}?g", "cdkkmlglglkcg" },+ { CMU, A, 0, 0, "[ace]{5}?", "AcCebDAcEEcEd" },+ { MU, A, 0, 0, "([AbC]{3,5}?d)+", "BACaAbbAEAACCbdCCbdCCAAbb" },+ { MU, A, 0, 0, "([^ab]{0,}s){2}", "abaabcdsABamsDDs" },+ { MU, A, 0, 0, "\\b\\w+\\B", "x,a_cd" },+ { MUP, A, 0, 0, "\\b[^\xc2\xa1]+\\B", "\xc3\x89\xc2\xa1\xe6\x92\xad\xc3\x81\xc3\xa1" },+ { CMU, A, 0, 0, "[^b]+(a*)([^c]?d{3})", "aaaaddd" },+ { CMUP, A, 0, 0, "\xe1\xbd\xb8{2}", "\xe1\xbf\xb8#\xe1\xbf\xb8\xe1\xbd\xb8" },+ { CMU, A, 0, 0, "[^\xf0\x90\x90\x80]{2,4}@", "\xf0\x90\x90\xa8\xf0\x90\x90\x80###\xf0\x90\x90\x80@@@" },+ { CMU, A, 0, 0, "[^\xe1\xbd\xb8][^\xc3\xa9]", "\xe1\xbd\xb8\xe1\xbf\xb8\xc3\xa9\xc3\x89#" },+ { MU, A, 0, 0, "[^\xe1\xbd\xb8][^\xc3\xa9]", "\xe1\xbd\xb8\xe1\xbf\xb8\xc3\xa9\xc3\x89#" },+ { MU, A, 0, 0, "[^\xe1\xbd\xb8]{3,}?", "##\xe1\xbd\xb8#\xe1\xbd\xb8#\xc3\x89#\xe1\xbd\xb8" },+ { MU, A, 0, 0, "\\d+123", "987654321,01234" },+ { MU, A, 0, 0, "abcd*|\\w+xy", "aaaaa,abxyz" },+ { MU, A, 0, 0, "(?:abc|((?:amc|\\b\\w*xy)))", "aaaaa,abxyz" },+ { MU, A, 0, 0, "a(?R)|([a-z]++)#", ".abcd.abcd#."},+ { MU, A, 0, 0, "a(?R)|([a-z]++)#", ".abcd.mbcd#."},+ { MU, A, 0, 0, ".[ab]*.", "xx" },+ { MU, A, 0, 0, ".[ab]*a", "xxa" },+ { MU, A, 0, 0, ".[ab]?.", "xx" },+ { MU, A, 0, 0, "_[ab]+_*a", "_aa" },++ /* Bracket repeats with limit. */+ { MU, A, 0, 0, "(?:(ab){2}){5}M", "abababababababababababM" },+ { MU, A, 0, 0, "(?:ab|abab){1,5}M", "abababababababababababM" },+ { MU, A, 0, 0, "(?>ab|abab){1,5}M", "abababababababababababM" },+ { MU, A, 0, 0, "(?:ab|abab){1,5}?M", "abababababababababababM" },+ { MU, A, 0, 0, "(?>ab|abab){1,5}?M", "abababababababababababM" },+ { MU, A, 0, 0, "(?:(ab){1,4}?){1,3}?M", "abababababababababababababM" },+ { MU, A, 0, 0, "(?:(ab){1,4}){1,3}abababababababababababM", "ababababababababababababM" },+ { MU, A, 0, 0 | F_NOMATCH, "(?:(ab){1,4}){1,3}abababababababababababM", "abababababababababababM" },+ { MU, A, 0, 0, "(ab){4,6}?M", "abababababababM" },++ /* Basic character sets. */+ { MU, A, 0, 0, "(?:\\s)+(?:\\S)+", "ab \t\xc3\xa9\xe6\x92\xad " },+ { MU, A, 0, 0, "(\\w)*(k)(\\W)?\?", "abcdef abck11" },+ { MU, A, 0, 0, "\\((\\d)+\\)\\D", "a() (83 (8)2 (9)ab" },+ { MU, A, 0, 0, "\\w(\\s|(?:\\d)*,)+\\w\\wb", "a 5, 4,, bb 5, 4,, aab" },+ { MU, A, 0, 0, "(\\v+)(\\V+)", "\x0e\xc2\x85\xe2\x80\xa8\x0b\x09\xe2\x80\xa9" },+ { MU, A, 0, 0, "(\\h+)(\\H+)", "\xe2\x80\xa8\xe2\x80\x80\x20\xe2\x80\x8a\xe2\x81\x9f\xe3\x80\x80\x09\x20\xc2\xa0\x0a" },+ { MU, A, 0, 0, "x[bcef]+", "xaxdxecbfg" },+ { MU, A, 0, 0, "x[bcdghij]+", "xaxexfxdgbjk" },+ { MU, A, 0, 0, "x[^befg]+", "xbxexacdhg" },+ { MU, A, 0, 0, "x[^bcdl]+", "xlxbxaekmd" },+ { MU, A, 0, 0, "x[^bcdghi]+", "xbxdxgxaefji" },+ { MU, A, 0, 0, "x[B-Fb-f]+", "xaxAxgxbfBFG" },+ { CMU, A, 0, 0, "\\x{e9}+", "#\xf0\x90\x90\xa8\xc3\xa8\xc3\xa9\xc3\x89\xc3\x88" },+ { CMU, A, 0, 0, "[^\\x{e9}]+", "\xc3\xa9#\xf0\x90\x90\xa8\xc3\xa8\xc3\x88\xc3\x89" },+ { MU, A, 0, 0, "[\\x02\\x7e]+", "\xc3\x81\xe1\xbf\xb8\xf0\x90\x90\xa8\x01\x02\x7e\x7f" },+ { MU, A, 0, 0, "[^\\x02\\x7e]+", "\x02\xc3\x81\xe1\xbf\xb8\xf0\x90\x90\xa8\x01\x7f\x7e" },+ { MU, A, 0, 0, "[\\x{81}-\\x{7fe}]+", "#\xe1\xbf\xb8\xf0\x90\x90\xa8\xc2\x80\xc2\x81\xdf\xbe\xdf\xbf" },+ { MU, A, 0, 0, "[^\\x{81}-\\x{7fe}]+", "\xc2\x81#\xe1\xbf\xb8\xf0\x90\x90\xa8\xc2\x80\xdf\xbf\xdf\xbe" },+ { MU, A, 0, 0, "[\\x{801}-\\x{fffe}]+", "#\xc3\xa9\xf0\x90\x90\x80\xe0\xa0\x80\xe0\xa0\x81\xef\xbf\xbe\xef\xbf\xbf" },+ { MU, A, 0, 0, "[^\\x{801}-\\x{fffe}]+", "\xe0\xa0\x81#\xc3\xa9\xf0\x90\x90\x80\xe0\xa0\x80\xef\xbf\xbf\xef\xbf\xbe" },+ { MU, A, 0, 0, "[\\x{10001}-\\x{10fffe}]+", "#\xc3\xa9\xe2\xb1\xa5\xf0\x90\x80\x80\xf0\x90\x80\x81\xf4\x8f\xbf\xbe\xf4\x8f\xbf\xbf" },+ { MU, A, 0, 0, "[^\\x{10001}-\\x{10fffe}]+", "\xf0\x90\x80\x81#\xc3\xa9\xe2\xb1\xa5\xf0\x90\x80\x80\xf4\x8f\xbf\xbf\xf4\x8f\xbf\xbe" },+ { CMU, A, 0, 0 | F_NOMATCH, "^[\\x{0100}-\\x{017f}]", " " },++ /* Unicode properties. */+ { MUP, A, 0, 0, "[1-5\xc3\xa9\\w]", "\xc3\xa1_" },+ { MUP, A, 0, 0 | F_PROPERTY, "[\xc3\x81\\p{Ll}]", "A_\xc3\x89\xc3\xa1" },+ { MUP, A, 0, 0, "[\\Wd-h_x-z]+", "a\xc2\xa1#_yhzdxi" },+ { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[\\P{Any}]", "abc" },+ { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[^\\p{Any}]", "abc" },+ { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[\\P{Any}\xc3\xa1-\xc3\xa8]", "abc" },+ { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[^\\p{Any}\xc3\xa1-\xc3\xa8]", "abc" },+ { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[\xc3\xa1-\xc3\xa8\\P{Any}]", "abc" },+ { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[^\xc3\xa1-\xc3\xa8\\p{Any}]", "abc" },+ { MUP, A, 0, 0 | F_PROPERTY, "[\xc3\xa1-\xc3\xa8\\p{Any}]", "abc" },+ { MUP, A, 0, 0 | F_PROPERTY, "[^\xc3\xa1-\xc3\xa8\\P{Any}]", "abc" },+ { MUP, A, 0, 0, "[b-\xc3\xa9\\s]", "a\xc\xe6\x92\xad" },+ { CMUP, A, 0, 0, "[\xc2\x85-\xc2\x89\xc3\x89]", "\xc2\x84\xc3\xa9" },+ { MUP, A, 0, 0, "[^b-d^&\\s]{3,}", "db^ !a\xe2\x80\xa8_ae" },+ { MUP, A, 0, 0 | F_PROPERTY, "[^\\S\\P{Any}][\\sN]{1,3}[\\P{N}]{4}", "\xe2\x80\xaa\xa N\x9\xc3\xa9_0" },+ { MU, A, 0, 0 | F_PROPERTY, "[^\\P{L}\x9!D-F\xa]{2,3}", "\x9,.DF\xa.CG\xc3\x81" },+ { CMUP, A, 0, 0, "[\xc3\xa1-\xc3\xa9_\xe2\x80\xa0-\xe2\x80\xaf]{1,5}[^\xe2\x80\xa0-\xe2\x80\xaf]", "\xc2\xa1\xc3\x89\xc3\x89\xe2\x80\xaf_\xe2\x80\xa0" },+ { MUP, A, 0, 0 | F_PROPERTY, "[\xc3\xa2-\xc3\xa6\xc3\x81-\xc3\x84\xe2\x80\xa8-\xe2\x80\xa9\xe6\x92\xad\\p{Zs}]{2,}", "\xe2\x80\xa7\xe2\x80\xa9\xe6\x92\xad \xe6\x92\xae" },+ { MUP, A, 0, 0 | F_PROPERTY, "[\\P{L&}]{2}[^\xc2\x85-\xc2\x89\\p{Ll}\\p{Lu}]{2}", "\xc3\xa9\xe6\x92\xad.a\xe6\x92\xad|\xc2\x8a#" },+ { PCRE2_UCP, 0, 0, 0 | F_PROPERTY, "[a-b\\s]{2,5}[^a]", "AB baaa" },+ { MUP, 0, 0, 0 | F_NOMATCH, "[^\\p{Hangul}\\p{Z}]", " " },++ /* Possible empty brackets. */+ { MU, A, 0, 0, "(?:|ab||bc|a)+d", "abcxabcabd" },+ { MU, A, 0, 0, "(|ab||bc|a)+d", "abcxabcabd" },+ { MU, A, 0, 0, "(?:|ab||bc|a)*d", "abcxabcabd" },+ { MU, A, 0, 0, "(|ab||bc|a)*d", "abcxabcabd" },+ { MU, A, 0, 0, "(?:|ab||bc|a)+?d", "abcxabcabd" },+ { MU, A, 0, 0, "(|ab||bc|a)+?d", "abcxabcabd" },+ { MU, A, 0, 0, "(?:|ab||bc|a)*?d", "abcxabcabd" },+ { MU, A, 0, 0, "(|ab||bc|a)*?d", "abcxabcabd" },+ { MU, A, 0, 0, "(((a)*?|(?:ba)+)+?|(?:|c|ca)*)*m", "abaacaccabacabalabaacaccabacabamm" },+ { MU, A, 0, 0, "(?:((?:a)*|(ba)+?)+|(|c|ca)*?)*?m", "abaacaccabacabalabaacaccabacabamm" },++ /* Start offset. */+ { MU, A, 0, 3, "(\\d|(?:\\w)*\\w)+", "0ac01Hb" },+ { MU, A, 0, 4 | F_NOMATCH, "(\\w\\W\\w)+", "ab#d" },+ { MU, A, 0, 2 | F_NOMATCH, "(\\w\\W\\w)+", "ab#d" },+ { MU, A, 0, 1, "(\\w\\W\\w)+", "ab#d" },++ /* Newline. */+ { M, PCRE2_NEWLINE_CRLF, 0, 0, "\\W{0,2}[^#]{3}", "\r\n#....." },+ { M, PCRE2_NEWLINE_CR, 0, 0, "\\W{0,2}[^#]{3}", "\r\n#....." },+ { M, PCRE2_NEWLINE_CRLF, 0, 0, "\\W{1,3}[^#]", "\r\n##...." },+ { MU, A, PCRE2_NO_UTF_CHECK, 1, "^.a", "\n\x80\nxa" },+ { MU, A, 0, 1, "^", "\r\n" },+ { M, PCRE2_NEWLINE_CRLF, 0, 1 | F_NOMATCH, "^", "\r\n" },+ { M, PCRE2_NEWLINE_CRLF, 0, 1, "^", "\r\na" },++ /* Any character except newline or any newline. */+ { 0, PCRE2_NEWLINE_CRLF, 0, 0, ".", "\r" },+ { U, PCRE2_NEWLINE_CRLF, 0, 0, ".(.).", "a\xc3\xa1\r\n\n\r\r" },+ { 0, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".(.)", "a\rb\nc\r\n\xc2\x85\xe2\x80\xa8" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".(.)", "a\rb\nc\r\n\xc2\x85\xe2\x80\xa8" },+ { U, PCRE2_NEWLINE_ANY, 0, 0, "(.).", "a\rb\nc\r\n\xc2\x85\xe2\x80\xa9$de" },+ { U, PCRE2_NEWLINE_ANYCRLF, 0, 0 | F_NOMATCH, ".(.).", "\xe2\x80\xa8\nb\r" },+ { 0, PCRE2_NEWLINE_ANY, 0, 0, "(.)(.)", "#\x85#\r#\n#\r\n#\x84" },+ { U, PCRE2_NEWLINE_ANY, 0, 0, "(.+)#", "#\rMn\xc2\x85#\n###" },+ { 0, BSR(PCRE2_BSR_ANYCRLF), 0, 0, "\\R", "\r" },+ { 0, BSR(PCRE2_BSR_ANYCRLF), 0, 0, "\\R", "\x85#\r\n#" },+ { U, BSR(PCRE2_BSR_UNICODE), 0, 0, "\\R", "ab\xe2\x80\xa8#c" },+ { U, BSR(PCRE2_BSR_UNICODE), 0, 0, "\\R", "ab\r\nc" },+ { U, PCRE2_NEWLINE_CRLF | BSR(PCRE2_BSR_UNICODE), 0, 0, "(\\R.)+", "\xc2\x85\r\n#\xe2\x80\xa8\n\r\n\r" },+ { MU, A, 0, 0 | F_NOMATCH, "\\R+", "ab" },+ { MU, A, 0, 0, "\\R+", "ab\r\n\r" },+ { MU, A, 0, 0, "\\R*", "ab\r\n\r" },+ { MU, A, 0, 0, "\\R*", "\r\n\r" },+ { MU, A, 0, 0, "\\R{2,4}", "\r\nab\r\r" },+ { MU, A, 0, 0, "\\R{2,4}", "\r\nab\n\n\n\r\r\r" },+ { MU, A, 0, 0, "\\R{2,}", "\r\nab\n\n\n\r\r\r" },+ { MU, A, 0, 0, "\\R{0,3}", "\r\n\r\n\r\n\r\n\r\n" },+ { MU, A, 0, 0 | F_NOMATCH, "\\R+\\R\\R", "\r\n\r\n" },+ { MU, A, 0, 0, "\\R+\\R\\R", "\r\r\r" },+ { MU, A, 0, 0, "\\R*\\R\\R", "\n\r" },+ { MU, A, 0, 0 | F_NOMATCH, "\\R{2,4}\\R\\R", "\r\r\r" },+ { MU, A, 0, 0, "\\R{2,4}\\R\\R", "\r\r\r\r" },++ /* Atomic groups (no fallback from "next" direction). */+ { MU, A, 0, 0 | F_NOMATCH, "(?>ab)ab", "bab" },+ { MU, A, 0, 0 | F_NOMATCH, "(?>(ab))ab", "bab" },+ { MU, A, 0, 0, "(?>ab)+abc(?>de)*def(?>gh)?ghe(?>ij)+?k(?>lm)*?n(?>op)?\?op",+ "bababcdedefgheijijklmlmnop" },+ { MU, A, 0, 0, "(?>a(b)+a|(ab)?\?(b))an", "abban" },+ { MU, A, 0, 0, "(?>ab+a|(?:ab)?\?b)an", "abban" },+ { MU, A, 0, 0, "((?>ab|ad|)*?)(?>|c)*abad", "abababcababad" },+ { MU, A, 0, 0, "(?>(aa|b|)*+(?>(##)|###)*d|(aa)(?>(baa)?)m)", "aabaa#####da" },+ { MU, A, 0, 0, "((?>a|)+?)b", "aaacaaab" },+ { MU, A, 0, 0, "(?>x|)*$", "aaa" },+ { MU, A, 0, 0, "(?>(x)|)*$", "aaa" },+ { MU, A, 0, 0, "(?>x|())*$", "aaa" },+ { MU, A, 0, 0, "((?>[cxy]a|[a-d])*?)b", "aaa+ aaab" },+ { MU, A, 0, 0, "((?>[cxy](a)|[a-d])*?)b", "aaa+ aaab" },+ { MU, A, 0, 0, "(?>((?>(a+))))bab|(?>((?>(a+))))bb", "aaaabaaabaabab" },+ { MU, A, 0, 0, "(?>(?>a+))bab|(?>(?>a+))bb", "aaaabaaabaabab" },+ { MU, A, 0, 0, "(?>(a)c|(?>(c)|(a))a)b*?bab", "aaaabaaabaabab" },+ { MU, A, 0, 0, "(?>ac|(?>c|a)a)b*?bab", "aaaabaaabaabab" },+ { MU, A, 0, 0, "(?>(b)b|(a))*b(?>(c)|d)?x", "ababcaaabdbx" },+ { MU, A, 0, 0, "(?>bb|a)*b(?>c|d)?x", "ababcaaabdbx" },+ { MU, A, 0, 0, "(?>(bb)|a)*b(?>c|(d))?x", "ababcaaabdbx" },+ { MU, A, 0, 0, "(?>(a))*?(?>(a))+?(?>(a))??x", "aaaaaacccaaaaabax" },+ { MU, A, 0, 0, "(?>a)*?(?>a)+?(?>a)??x", "aaaaaacccaaaaabax" },+ { MU, A, 0, 0, "(?>(a)|)*?(?>(a)|)+?(?>(a)|)??x", "aaaaaacccaaaaabax" },+ { MU, A, 0, 0, "(?>a|)*?(?>a|)+?(?>a|)??x", "aaaaaacccaaaaabax" },+ { MU, A, 0, 0, "(?>a(?>(a{0,2}))*?b|aac)+b", "aaaaaaacaaaabaaaaacaaaabaacaaabb" },+ { CM, A, 0, 0, "(?>((?>a{32}|b+|(a*))?(?>c+|d*)?\?)+e)+?f", "aaccebbdde bbdaaaccebbdee bbdaaaccebbdeef" },+ { MU, A, 0, 0, "(?>(?:(?>aa|a||x)+?b|(?>aa|a||(x))+?c)?(?>[ad]{0,2})*?d)+d", "aaacdbaabdcabdbaaacd aacaabdbdcdcaaaadaabcbaadd" },+ { MU, A, 0, 0, "(?>(?:(?>aa|a||(x))+?b|(?>aa|a||x)+?c)?(?>[ad]{0,2})*?d)+d", "aaacdbaabdcabdbaaacd aacaabdbdcdcaaaadaabcbaadd" },+ { MU, A, 0, 0 | F_PROPERTY, "\\X", "\xcc\x8d\xcc\x8d" },+ { MU, A, 0, 0 | F_PROPERTY, "\\X", "\xcc\x8d\xcc\x8d#\xcc\x8d\xcc\x8d" },+ { MU, A, 0, 0 | F_PROPERTY, "\\X+..", "\xcc\x8d#\xcc\x8d#\xcc\x8d\xcc\x8d" },+ { MU, A, 0, 0 | F_PROPERTY, "\\X{2,4}", "abcdef" },+ { MU, A, 0, 0 | F_PROPERTY, "\\X{2,4}?", "abcdef" },+ { MU, A, 0, 0 | F_NOMATCH | F_PROPERTY, "\\X{2,4}..", "#\xcc\x8d##" },+ { MU, A, 0, 0 | F_PROPERTY, "\\X{2,4}..", "#\xcc\x8d#\xcc\x8d##" },+ { MU, A, 0, 0, "(c(ab)?+ab)+", "cabcababcab" },+ { MU, A, 0, 0, "(?>(a+)b)+aabab", "aaaabaaabaabab" },++ /* Possessive quantifiers. */+ { MU, A, 0, 0, "(?:a|b)++m", "mababbaaxababbaam" },+ { MU, A, 0, 0, "(?:a|b)*+m", "mababbaaxababbaam" },+ { MU, A, 0, 0, "(?:a|b)*+m", "ababbaaxababbaam" },+ { MU, A, 0, 0, "(a|b)++m", "mababbaaxababbaam" },+ { MU, A, 0, 0, "(a|b)*+m", "mababbaaxababbaam" },+ { MU, A, 0, 0, "(a|b)*+m", "ababbaaxababbaam" },+ { MU, A, 0, 0, "(a|b(*ACCEPT))++m", "maaxab" },+ { MU, A, 0, 0, "(?:b*)++m", "bxbbxbbbxm" },+ { MU, A, 0, 0, "(?:b*)++m", "bxbbxbbbxbbm" },+ { MU, A, 0, 0, "(?:b*)*+m", "bxbbxbbbxm" },+ { MU, A, 0, 0, "(?:b*)*+m", "bxbbxbbbxbbm" },+ { MU, A, 0, 0, "(b*)++m", "bxbbxbbbxm" },+ { MU, A, 0, 0, "(b*)++m", "bxbbxbbbxbbm" },+ { MU, A, 0, 0, "(b*)*+m", "bxbbxbbbxm" },+ { MU, A, 0, 0, "(b*)*+m", "bxbbxbbbxbbm" },+ { MU, A, 0, 0, "(?:a|(b))++m", "mababbaaxababbaam" },+ { MU, A, 0, 0, "(?:(a)|b)*+m", "mababbaaxababbaam" },+ { MU, A, 0, 0, "(?:(a)|(b))*+m", "ababbaaxababbaam" },+ { MU, A, 0, 0, "(a|(b))++m", "mababbaaxababbaam" },+ { MU, A, 0, 0, "((a)|b)*+m", "mababbaaxababbaam" },+ { MU, A, 0, 0, "((a)|(b))*+m", "ababbaaxababbaam" },+ { MU, A, 0, 0, "(a|(b)(*ACCEPT))++m", "maaxab" },+ { MU, A, 0, 0, "(?:(b*))++m", "bxbbxbbbxm" },+ { MU, A, 0, 0, "(?:(b*))++m", "bxbbxbbbxbbm" },+ { MU, A, 0, 0, "(?:(b*))*+m", "bxbbxbbbxm" },+ { MU, A, 0, 0, "(?:(b*))*+m", "bxbbxbbbxbbm" },+ { MU, A, 0, 0, "((b*))++m", "bxbbxbbbxm" },+ { MU, A, 0, 0, "((b*))++m", "bxbbxbbbxbbm" },+ { MU, A, 0, 0, "((b*))*+m", "bxbbxbbbxm" },+ { MU, A, 0, 0, "((b*))*+m", "bxbbxbbbxbbm" },+ { MU, A, 0, 0 | F_NOMATCH, "(?>(b{2,4}))(?:(?:(aa|c))++m|(?:(aa|c))+n)", "bbaacaaccaaaacxbbbmbn" },+ { MU, A, 0, 0, "((?:b)++a)+(cd)*+m", "bbababbacdcdnbbababbacdcdm" },+ { MU, A, 0, 0, "((?:(b))++a)+((c)d)*+m", "bbababbacdcdnbbababbacdcdm" },+ { MU, A, 0, 0, "(?:(?:(?:ab)*+k)++(?:n(?:cd)++)*+)*+m", "ababkkXababkkabkncXababkkabkncdcdncdXababkkabkncdcdncdkkabkncdXababkkabkncdcdncdkkabkncdm" },+ { MU, A, 0, 0, "(?:((ab)*+(k))++(n(?:c(d))++)*+)*+m", "ababkkXababkkabkncXababkkabkncdcdncdXababkkabkncdcdncdkkabkncdXababkkabkncdcdncdkkabkncdm" },++ /* Back references. */+ { MU, A, 0, 0, "(aa|bb)(\\1*)(ll|)(\\3*)bbbbbbc", "aaaaaabbbbbbbbc" },+ { CMU, A, 0, 0, "(aa|bb)(\\1+)(ll|)(\\3+)bbbbbbc", "bBbbBbCbBbbbBbbcbbBbbbBBbbC" },+ { CM, A, 0, 0, "(a{2,4})\\1", "AaAaaAaA" },+ { MU, A, 0, 0, "(aa|bb)(\\1?)aa(\\1?)(ll|)(\\4+)bbc", "aaaaaaaabbaabbbbaabbbbc" },+ { MU, A, 0, 0, "(aa|bb)(\\1{0,5})(ll|)(\\3{0,5})cc", "bbxxbbbbxxaaaaaaaaaaaaaaaacc" },+ { MU, A, 0, 0, "(aa|bb)(\\1{3,5})(ll|)(\\3{3,5})cc", "bbbbbbbbbbbbaaaaaaccbbbbbbbbbbbbbbcc" },+ { MU, A, 0, 0, "(aa|bb)(\\1{3,})(ll|)(\\3{3,})cc", "bbbbbbbbbbbbaaaaaaccbbbbbbbbbbbbbbcc" },+ { MU, A, 0, 0, "(\\w+)b(\\1+)c", "GabGaGaDbGaDGaDc" },+ { MU, A, 0, 0, "(?:(aa)|b)\\1?b", "bb" },+ { CMU, A, 0, 0, "(aa|bb)(\\1*?)aa(\\1+?)", "bBBbaaAAaaAAaa" },+ { MU, A, 0, 0, "(aa|bb)(\\1*?)(dd|)cc(\\3+?)", "aaaaaccdd" },+ { CMU, A, 0, 0, "(?:(aa|bb)(\\1?\?)cc){2}(\\1?\?)", "aAaABBbbAAaAcCaAcCaA" },+ { MU, A, 0, 0, "(?:(aa|bb)(\\1{3,5}?)){2}(dd|)(\\3{3,5}?)", "aaaaaabbbbbbbbbbaaaaaaaaaaaaaa" },+ { CM, A, 0, 0, "(?:(aa|bb)(\\1{3,}?)){2}(dd|)(\\3{3,}?)", "aaaaaabbbbbbbbbbaaaaaaaaaaaaaa" },+ { MU, A, 0, 0, "(?:(aa|bb)(\\1{0,3}?)){2}(dd|)(\\3{0,3}?)b(\\1{0,3}?)(\\1{0,3})", "aaaaaaaaaaaaaaabaaaaa" },+ { MU, A, 0, 0, "(a(?:\\1|)a){3}b", "aaaaaaaaaaab" },+ { M, A, 0, 0, "(a?)b(\\1\\1*\\1+\\1?\\1*?\\1+?\\1??\\1*+\\1++\\1?+\\1{4}\\1{3,5}\\1{4,}\\1{0,5}\\1{3,5}?\\1{4,}?\\1{0,5}?\\1{3,5}+\\1{4,}+\\1{0,5}+#){2}d", "bb#b##d" },+ { MUP, A, 0, 0 | F_PROPERTY, "(\\P{N})\\1{2,}", ".www." },+ { MUP, A, 0, 0 | F_PROPERTY, "(\\P{N})\\1{0,2}", "wwwww." },+ { MUP, A, 0, 0 | F_PROPERTY, "(\\P{N})\\1{1,2}ww", "wwww" },+ { MUP, A, 0, 0 | F_PROPERTY, "(\\P{N})\\1{1,2}ww", "wwwww" },+ { PCRE2_UCP, 0, 0, 0 | F_PROPERTY, "(\\P{N})\\1{2,}", ".www." },+ { CMUP, A, 0, 0, "(\xf0\x90\x90\x80)\\1", "\xf0\x90\x90\xa8\xf0\x90\x90\xa8" },+ { MU | PCRE2_DUPNAMES, A, 0, 0 | F_NOMATCH, "\\k<A>{1,3}(?<A>aa)(?<A>bb)", "aabb" },+ { MU | PCRE2_DUPNAMES | PCRE2_MATCH_UNSET_BACKREF, A, 0, 0, "\\k<A>{1,3}(?<A>aa)(?<A>bb)", "aabb" },+ { MU | PCRE2_DUPNAMES | PCRE2_MATCH_UNSET_BACKREF, A, 0, 0, "\\k<A>*(?<A>aa)(?<A>bb)", "aabb" },+ { MU | PCRE2_DUPNAMES, A, 0, 0, "(?<A>aa)(?<A>bb)\\k<A>{0,3}aaaaaa", "aabbaaaaaa" },+ { MU | PCRE2_DUPNAMES, A, 0, 0, "(?<A>aa)(?<A>bb)\\k<A>{2,5}bb", "aabbaaaabb" },+ { MU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>aa)|(?<A>bb))\\k<A>{0,3}m", "aaaaaaaabbbbaabbbbm" },+ { MU | PCRE2_DUPNAMES, A, 0, 0 | F_NOMATCH, "\\k<A>{1,3}?(?<A>aa)(?<A>bb)", "aabb" },+ { MU | PCRE2_DUPNAMES | PCRE2_MATCH_UNSET_BACKREF, A, 0, 0, "\\k<A>{1,3}?(?<A>aa)(?<A>bb)", "aabb" },+ { MU | PCRE2_DUPNAMES, A, 0, 0, "\\k<A>*?(?<A>aa)(?<A>bb)", "aabb" },+ { MU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>aa)|(?<A>bb))\\k<A>{0,3}?m", "aaaaaabbbbbbaabbbbbbbbbbm" },+ { MU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>aa)|(?<A>bb))\\k<A>*?m", "aaaaaabbbbbbaabbbbbbbbbbm" },+ { MU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>aa)|(?<A>bb))\\k<A>{2,3}?", "aaaabbbbaaaabbbbbbbbbb" },+ { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{0,3}M", "aaaaaaaabbbbaabbbbm" },+ { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{1,3}M", "aaaaaaaabbbbaabbbbm" },+ { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{0,3}?M", "aaaaaabbbbbbaabbbbbbbbbbm" },+ { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{2,3}?", "aaaabbbbaaaabbbbbbbbbb" },++ /* Assertions. */+ { MU, A, 0, 0, "(?=xx|yy|zz)\\w{4}", "abczzdefg" },+ { MU, A, 0, 0, "(?=((\\w+)b){3}|ab)", "dbbbb ab" },+ { MU, A, 0, 0, "(?!ab|bc|cd)[a-z]{2}", "Xabcdef" },+ { MU, A, 0, 0, "(?<=aaa|aa|a)a", "aaa" },+ { MU, A, 0, 2, "(?<=aaa|aa|a)a", "aaa" },+ { M, A, 0, 0, "(?<=aaa|aa|a)a", "aaa" },+ { M, A, 0, 2, "(?<=aaa|aa|a)a", "aaa" },+ { MU, A, 0, 0, "(\\d{2})(?!\\w+c|(((\\w?)m){2}n)+|\\1)", "x5656" },+ { MU, A, 0, 0, "((?=((\\d{2,6}\\w){2,}))\\w{5,20}K){2,}", "567v09708K12l00M00 567v09708K12l00M00K45K" },+ { MU, A, 0, 0, "(?=(?:(?=\\S+a)\\w*(b)){3})\\w+\\d", "bba bbab nbbkba nbbkba0kl" },+ { MU, A, 0, 0, "(?>a(?>(b+))a(?=(..)))*?k", "acabbcabbaabacabaabbakk" },+ { MU, A, 0, 0, "((?(?=(a))a)+k)", "bbak" },+ { MU, A, 0, 0, "((?(?=a)a)+k)", "bbak" },+ { MU, A, 0, 0 | F_NOMATCH, "(?=(?>(a))m)amk", "a k" },+ { MU, A, 0, 0 | F_NOMATCH, "(?!(?>(a))m)amk", "a k" },+ { MU, A, 0, 0 | F_NOMATCH, "(?>(?=(a))am)amk", "a k" },+ { MU, A, 0, 0, "(?=(?>a|(?=(?>(b+))a|c)[a-c]+)*?m)[a-cm]+k", "aaam bbam baaambaam abbabba baaambaamk" },+ { MU, A, 0, 0, "(?> ?\?\\b(?(?=\\w{1,4}(a))m)\\w{0,8}bc){2,}?", "bca ssbc mabd ssbc mabc" },+ { MU, A, 0, 0, "(?:(?=ab)?[^n][^n])+m", "ababcdabcdcdabnababcdabcdcdabm" },+ { MU, A, 0, 0, "(?:(?=a(b))?[^n][^n])+m", "ababcdabcdcdabnababcdabcdcdabm" },+ { MU, A, 0, 0, "(?:(?=.(.))??\\1.)+m", "aabbbcbacccanaabbbcbacccam" },+ { MU, A, 0, 0, "(?:(?=.)??[a-c])+m", "abacdcbacacdcaccam" },+ { MU, A, 0, 0, "((?!a)?(?!([^a]))?)+$", "acbab" },+ { MU, A, 0, 0, "((?!a)?\?(?!([^a]))?\?)+$", "acbab" },+ { MU, A, 0, 0, "a(?=(?C)\\B(?C`x`))b", "ab" },+ { MU, A, 0, 0, "a(?!(?C)\\B(?C`x`))bb|ab", "abb" },+ { MU, A, 0, 0, "a(?=\\b|(?C)\\B(?C`x`))b", "ab" },+ { MU, A, 0, 0, "a(?!\\b|(?C)\\B(?C`x`))bb|ab", "abb" },+ { MU, A, 0, 0, "c(?(?=(?C)\\B(?C`x`))ab|a)", "cab" },+ { MU, A, 0, 0, "c(?(?!(?C)\\B(?C`x`))ab|a)", "cab" },+ { MU, A, 0, 0, "c(?(?=\\b|(?C)\\B(?C`x`))ab|a)", "cab" },+ { MU, A, 0, 0, "c(?(?!\\b|(?C)\\B(?C`x`))ab|a)", "cab" },+ { MU, A, 0, 0, "a(?=)b", "ab" },+ { MU, A, 0, 0 | F_NOMATCH, "a(?!)b", "ab" },++ /* Not empty, ACCEPT, FAIL */+ { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a*", "bcx" },+ { MU, A, PCRE2_NOTEMPTY, 0, "a*", "bcaad" },+ { MU, A, PCRE2_NOTEMPTY, 0, "a*?", "bcaad" },+ { MU, A, PCRE2_NOTEMPTY_ATSTART, 0, "a*", "bcaad" },+ { MU, A, 0, 0, "a(*ACCEPT)b", "ab" },+ { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a*(*ACCEPT)b", "bcx" },+ { MU, A, PCRE2_NOTEMPTY, 0, "a*(*ACCEPT)b", "bcaad" },+ { MU, A, PCRE2_NOTEMPTY, 0, "a*?(*ACCEPT)b", "bcaad" },+ { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "(?:z|a*(*ACCEPT)b)", "bcx" },+ { MU, A, PCRE2_NOTEMPTY, 0, "(?:z|a*(*ACCEPT)b)", "bcaad" },+ { MU, A, PCRE2_NOTEMPTY, 0, "(?:z|a*?(*ACCEPT)b)", "bcaad" },+ { MU, A, PCRE2_NOTEMPTY_ATSTART, 0, "a*(*ACCEPT)b", "bcx" },+ { MU, A, PCRE2_NOTEMPTY_ATSTART, 0 | F_NOMATCH, "a*(*ACCEPT)b", "" },+ { MU, A, 0, 0, "((a(*ACCEPT)b))", "ab" },+ { MU, A, 0, 0, "(a(*FAIL)a|a)", "aaa" },+ { MU, A, 0, 0, "(?=ab(*ACCEPT)b)a", "ab" },+ { MU, A, 0, 0, "(?=(?:x|ab(*ACCEPT)b))", "ab" },+ { MU, A, 0, 0, "(?=(a(b(*ACCEPT)b)))a", "ab" },+ { MU, A, PCRE2_NOTEMPTY, 0, "(?=a*(*ACCEPT))c", "c" },+ { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "(?=A)", "AB" },++ /* Conditional blocks. */+ { MU, A, 0, 0, "(?(?=(a))a|b)+k", "ababbalbbadabak" },+ { MU, A, 0, 0, "(?(?!(b))a|b)+k", "ababbalbbadabak" },+ { MU, A, 0, 0, "(?(?=a)a|b)+k", "ababbalbbadabak" },+ { MU, A, 0, 0, "(?(?!b)a|b)+k", "ababbalbbadabak" },+ { MU, A, 0, 0, "(?(?=(a))a*|b*)+k", "ababbalbbadabak" },+ { MU, A, 0, 0, "(?(?!(b))a*|b*)+k", "ababbalbbadabak" },+ { MU, A, 0, 0, "(?(?!(b))(?:aaaaaa|a)|(?:bbbbbb|b))+aaaak", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb aaaaaaak" },+ { MU, A, 0, 0, "(?(?!b)(?:aaaaaa|a)|(?:bbbbbb|b))+aaaak", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb aaaaaaak" },+ { MU, A, 0, 0 | F_DIFF, "(?(?!(b))(?:aaaaaa|a)|(?:bbbbbb|b))+bbbbk", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb bbbbbbbk" },+ { MU, A, 0, 0, "(?(?!b)(?:aaaaaa|a)|(?:bbbbbb|b))+bbbbk", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb bbbbbbbk" },+ { MU, A, 0, 0, "(?(?=a)a*|b*)+k", "ababbalbbadabak" },+ { MU, A, 0, 0, "(?(?!b)a*|b*)+k", "ababbalbbadabak" },+ { MU, A, 0, 0, "(?(?=a)ab)", "a" },+ { MU, A, 0, 0, "(?(?<!b)c)", "b" },+ { MU, A, 0, 0, "(?(DEFINE)a(b))", "a" },+ { MU, A, 0, 0, "a(?(DEFINE)(?:b|(?:c?)+)*)", "a" },+ { MU, A, 0, 0, "(?(?=.[a-c])[k-l]|[A-D])", "kdB" },+ { MU, A, 0, 0, "(?(?!.{0,4}[cd])(aa|bb)|(cc|dd))+", "aabbccddaa" },+ { MU, A, 0, 0, "(?(?=[^#@]*@)(aaab|aa|aba)|(aba|aab)){3,}", "aaabaaaba#aaabaaaba#aaabaaaba@" },+ { MU, A, 0, 0, "((?=\\w{5})\\w(?(?=\\w*k)\\d|[a-f_])*\\w\\s)+", "mol m10kk m088k _f_a_ mbkkl" },+ { MU, A, 0, 0, "(c)?\?(?(1)a|b)", "cdcaa" },+ { MU, A, 0, 0, "(c)?\?(?(1)a|b)", "cbb" },+ { MU, A, 0, 0 | F_DIFF, "(?(?=(a))(aaaa|a?))+aak", "aaaaab aaaaak" },+ { MU, A, 0, 0, "(?(?=a)(aaaa|a?))+aak", "aaaaab aaaaak" },+ { MU, A, 0, 0, "(?(?!(b))(aaaa|a?))+aak", "aaaaab aaaaak" },+ { MU, A, 0, 0, "(?(?!b)(aaaa|a?))+aak", "aaaaab aaaaak" },+ { MU, A, 0, 0 | F_DIFF, "(?(?=(a))a*)+aak", "aaaaab aaaaak" },+ { MU, A, 0, 0, "(?(?=a)a*)+aak", "aaaaab aaaaak" },+ { MU, A, 0, 0, "(?(?!(b))a*)+aak", "aaaaab aaaaak" },+ { MU, A, 0, 0, "(?(?!b)a*)+aak", "aaaaab aaaaak" },+ { MU, A, 0, 0, "(?(?=(?=(?!(x))a)aa)aaa|(?(?=(?!y)bb)bbb))*k", "abaabbaaabbbaaabbb abaabbaaabbbaaabbbk" },+ { MU, A, 0, 0, "(?P<Name>a)?(?P<Name2>b)?(?(Name)c|d)*l", "bc ddd abccabccl" },+ { MU, A, 0, 0, "(?P<Name>a)?(?P<Name2>b)?(?(Name)c|d)+?dd", "bcabcacdb bdddd" },+ { MU, A, 0, 0, "(?P<Name>a)?(?P<Name2>b)?(?(Name)c|d)+l", "ababccddabdbccd abcccl" },+ { MU, A, 0, 0, "((?:a|aa)(?(1)aaa))x", "aax" },+ { MU, A, 0, 0, "(?(?!)a|b)", "ab" },+ { MU, A, 0, 0, "(?(?!)a)", "ab" },+ { MU, A, 0, 0 | F_NOMATCH, "(?(?!)a|b)", "ac" },++ /* Set start of match. */+ { MU, A, 0, 0, "(?:\\Ka)*aaaab", "aaaaaaaa aaaaaaabb" },+ { MU, A, 0, 0, "(?>\\Ka\\Ka)*aaaab", "aaaaaaaa aaaaaaaaaabb" },+ { MU, A, 0, 0, "a+\\K(?<=\\Gaa)a", "aaaaaa" },+ { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a\\K(*ACCEPT)b", "aa" },+ { MU, A, PCRE2_NOTEMPTY_ATSTART, 0, "a\\K(*ACCEPT)b", "aa" },++ /* First line. */+ { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_PROPERTY, "\\p{Any}a", "bb\naaa" },+ { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH | F_PROPERTY, "\\p{Any}a", "bb\r\naaa" },+ { MU | PCRE2_FIRSTLINE, A, 0, 0, "(?<=a)", "a" },+ { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH, "[^a][^b]", "ab" },+ { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH, "a", "\na" },+ { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH, "[abc]", "\na" },+ { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH, "^a", "\na" },+ { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH, "^(?<=\n)", "\na" },+ { MU | PCRE2_FIRSTLINE, A, 0, 0, "\xf0\x90\x90\x80", "\xf0\x90\x90\x80" },+ { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_ANY, 0, 0 | F_NOMATCH, "#", "\xc2\x85#" },+ { M | PCRE2_FIRSTLINE, PCRE2_NEWLINE_ANY, 0, 0 | F_NOMATCH, "#", "\x85#" },+ { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_ANY, 0, 0 | F_NOMATCH, "^#", "\xe2\x80\xa8#" },+ { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 0 | F_PROPERTY, "\\p{Any}", "\r\na" },+ { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 0, ".", "\r" },+ { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 0, "a", "\ra" },+ { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 0 | F_NOMATCH, "ba", "bbb\r\nba" },+ { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 0 | F_NOMATCH | F_PROPERTY, "\\p{Any}{4}|a", "\r\na" },+ { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 1, ".", "\r\n" },+ { PCRE2_FIRSTLINE | PCRE2_DOTALL, PCRE2_NEWLINE_LF, 0, 0 | F_NOMATCH, "ab.", "ab" },+ { MU | PCRE2_FIRSTLINE, A, 0, 1 | F_NOMATCH, "^[a-d0-9]", "\nxx\nd" },+ { PCRE2_FIRSTLINE | PCRE2_DOTALL, PCRE2_NEWLINE_ANY, 0, 0, "....a", "012\n0a" },+ { MU | PCRE2_FIRSTLINE, A, 0, 0, "[aC]", "a" },++ /* Recurse. */+ { MU, A, 0, 0, "(a)(?1)", "aa" },+ { MU, A, 0, 0, "((a))(?1)", "aa" },+ { MU, A, 0, 0, "(b|a)(?1)", "aa" },+ { MU, A, 0, 0, "(b|(a))(?1)", "aa" },+ { MU, A, 0, 0 | F_NOMATCH, "((a)(b)(?:a*))(?1)", "aba" },+ { MU, A, 0, 0, "((a)(b)(?:a*))(?1)", "abab" },+ { MU, A, 0, 0, "((a+)c(?2))b(?1)", "aacaabaca" },+ { MU, A, 0, 0, "((?2)b|(a)){2}(?1)", "aabab" },+ { MU, A, 0, 0, "(?1)(a)*+(?2)(b(?1))", "aababa" },+ { MU, A, 0, 0, "(?1)(((a(*ACCEPT)))b)", "axaa" },+ { MU, A, 0, 0, "(?1)(?(DEFINE) (((ac(*ACCEPT)))b) )", "akaac" },+ { MU, A, 0, 0, "(a+)b(?1)b\\1", "abaaabaaaaa" },+ { MU, A, 0, 0, "(?(DEFINE)(aa|a))(?1)ab", "aab" },+ { MU, A, 0, 0, "(?(DEFINE)(a\\Kb))(?1)+ababc", "abababxabababc" },+ { MU, A, 0, 0, "(a\\Kb)(?1)+ababc", "abababxababababc" },+ { MU, A, 0, 0 | F_NOMATCH, "(a\\Kb)(?1)+ababc", "abababxababababxc" },+ { MU, A, 0, 0, "b|<(?R)*>", "<<b>" },+ { MU, A, 0, 0, "(a\\K){0}(?:(?1)b|ac)", "ac" },+ { MU, A, 0, 0, "(?(DEFINE)(a(?2)|b)(b(?1)|(a)))(?:(?1)|(?2))m", "ababababnababababaam" },+ { MU, A, 0, 0, "(a)((?(R)a|b))(?2)", "aabbabaa" },+ { MU, A, 0, 0, "(a)((?(R2)a|b))(?2)", "aabbabaa" },+ { MU, A, 0, 0, "(a)((?(R1)a|b))(?2)", "ababba" },+ { MU, A, 0, 0, "(?(R0)aa|bb(?R))", "abba aabb bbaa" },+ { MU, A, 0, 0, "((?(R)(?:aaaa|a)|(?:(aaaa)|(a)))+)(?1)$", "aaaaaaaaaa aaaa" },+ { MU, A, 0, 0, "(?P<Name>a(?(R&Name)a|b))(?1)", "aab abb abaa" },+ { MU, A, 0, 0, "((?(R)a|(?1)){3})", "XaaaaaaaaaX" },+ { MU, A, 0, 0, "((?:(?(R)a|(?1))){3})", "XaaaaaaaaaX" },+ { MU, A, 0, 0, "((?(R)a|(?1)){1,3})aaaaaa", "aaaaaaaaXaaaaaaaaa" },+ { MU, A, 0, 0, "((?(R)a|(?1)){1,3}?)M", "aaaM" },+ { MU, A, 0, 0, "((.)(?:.|\\2(?1))){0}#(?1)#", "#aabbccdde# #aabbccddee#" },+ { MU, A, 0, 0, "((.)(?:\\2|\\2{4}b)){0}#(?:(?1))+#", "#aaaab# #aaaaab#" },++ /* 16 bit specific tests. */+ { CM, A, 0, 0 | F_FORCECONV, "\xc3\xa1", "\xc3\x81\xc3\xa1" },+ { CM, A, 0, 0 | F_FORCECONV, "\xe1\xbd\xb8", "\xe1\xbf\xb8\xe1\xbd\xb8" },+ { CM, A, 0, 0 | F_FORCECONV, "[\xc3\xa1]", "\xc3\x81\xc3\xa1" },+ { CM, A, 0, 0 | F_FORCECONV, "[\xe1\xbd\xb8]", "\xe1\xbf\xb8\xe1\xbd\xb8" },+ { CM, A, 0, 0 | F_FORCECONV, "[a-\xed\xb0\x80]", "A" },+ { CM, A, 0, 0 | F_NO8 | F_FORCECONV, "[a-\\x{dc00}]", "B" },+ { CM, A, 0, 0 | F_NO8 | F_NOMATCH | F_FORCECONV, "[b-\\x{dc00}]", "a" },+ { CM, A, 0, 0 | F_NO8 | F_FORCECONV, "\xed\xa0\x80\\x{d800}\xed\xb0\x80\\x{dc00}", "\xed\xa0\x80\xed\xa0\x80\xed\xb0\x80\xed\xb0\x80" },+ { CM, A, 0, 0 | F_NO8 | F_FORCECONV, "[\xed\xa0\x80\\x{d800}]{1,2}?[\xed\xb0\x80\\x{dc00}]{1,2}?#", "\xed\xa0\x80\xed\xa0\x80\xed\xb0\x80\xed\xb0\x80#" },+ { CM, A, 0, 0 | F_FORCECONV, "[\xed\xa0\x80\xed\xb0\x80#]{0,3}(?<=\xed\xb0\x80.)", "\xed\xa0\x80#\xed\xa0\x80##\xed\xb0\x80\xed\xa0\x80" },+ { CM, A, 0, 0 | F_FORCECONV, "[\xed\xa0\x80-\xed\xb3\xbf]", "\xed\x9f\xbf\xed\xa0\x83" },+ { CM, A, 0, 0 | F_FORCECONV, "[\xed\xa0\x80-\xed\xb3\xbf]", "\xed\xb4\x80\xed\xb3\xb0" },+ { CM, A, 0, 0 | F_NO8 | F_FORCECONV, "[\\x{d800}-\\x{dcff}]", "\xed\x9f\xbf\xed\xa0\x83" },+ { CM, A, 0, 0 | F_NO8 | F_FORCECONV, "[\\x{d800}-\\x{dcff}]", "\xed\xb4\x80\xed\xb3\xb0" },+ { CM, A, 0, 0 | F_FORCECONV, "[\xed\xa0\x80-\xef\xbf\xbf]+[\x1-\xed\xb0\x80]+#", "\xed\xa0\x85\xc3\x81\xed\xa0\x85\xef\xbf\xb0\xc2\x85\xed\xa9\x89#" },+ { CM, A, 0, 0 | F_FORCECONV, "[\xed\xa0\x80][\xed\xb0\x80]{2,}", "\xed\xa0\x80\xed\xb0\x80\xed\xa0\x80\xed\xb0\x80\xed\xb0\x80\xed\xb0\x80" },+ { M, A, 0, 0 | F_FORCECONV, "[^\xed\xb0\x80]{3,}?", "##\xed\xb0\x80#\xed\xb0\x80#\xc3\x89#\xed\xb0\x80" },+ { M, A, 0, 0 | F_NO8 | F_FORCECONV, "[^\\x{dc00}]{3,}?", "##\xed\xb0\x80#\xed\xb0\x80#\xc3\x89#\xed\xb0\x80" },+ { CM, A, 0, 0 | F_FORCECONV, ".\\B.", "\xed\xa0\x80\xed\xb0\x80" },+ { CM, A, 0, 0 | F_FORCECONV, "\\D+(?:\\d+|.)\\S+(?:\\s+|.)\\W+(?:\\w+|.)\xed\xa0\x80\xed\xa0\x80", "\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80" },+ { CM, A, 0, 0 | F_FORCECONV, "\\d*\\s*\\w*\xed\xa0\x80\xed\xa0\x80", "\xed\xa0\x80\xed\xa0\x80" },+ { CM, A, 0, 0 | F_FORCECONV | F_NOMATCH, "\\d*?\\D*?\\s*?\\S*?\\w*?\\W*?##", "\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80#" },+ { CM | PCRE2_EXTENDED, A, 0, 0 | F_FORCECONV, "\xed\xa0\x80 \xed\xb0\x80 !", "\xed\xa0\x80\xed\xb0\x80!" },+ { CM, A, 0, 0 | F_FORCECONV, "\xed\xa0\x80+#[^#]+\xed\xa0\x80", "\xed\xa0\x80#a\xed\xa0\x80" },+ { CM, A, 0, 0 | F_FORCECONV, "(\xed\xa0\x80+)#\\1", "\xed\xa0\x80\xed\xa0\x80#\xed\xa0\x80\xed\xa0\x80" },+ { M, PCRE2_NEWLINE_ANY, 0, 0 | F_NO8 | F_FORCECONV, "^-", "a--\xe2\x80\xa8--" },+ { 0, BSR(PCRE2_BSR_UNICODE), 0, 0 | F_NO8 | F_FORCECONV, "\\R", "ab\xe2\x80\xa8" },+ { 0, 0, 0, 0 | F_NO8 | F_FORCECONV, "\\v", "ab\xe2\x80\xa9" },+ { 0, 0, 0, 0 | F_NO8 | F_FORCECONV, "\\h", "ab\xe1\xa0\x8e" },+ { 0, 0, 0, 0 | F_NO8 | F_FORCECONV, "\\v+?\\V+?#", "\xe2\x80\xa9\xe2\x80\xa9\xef\xbf\xbf\xef\xbf\xbf#" },+ { 0, 0, 0, 0 | F_NO8 | F_FORCECONV, "\\h+?\\H+?#", "\xe1\xa0\x8e\xe1\xa0\x8e\xef\xbf\xbf\xef\xbf\xbf#" },++ /* Partial matching. */+ { MU, A, PCRE2_PARTIAL_SOFT, 0, "ab", "a" },+ { MU, A, PCRE2_PARTIAL_SOFT, 0, "ab|a", "a" },+ { MU, A, PCRE2_PARTIAL_HARD, 0, "ab|a", "a" },+ { MU, A, PCRE2_PARTIAL_SOFT, 0, "\\b#", "a" },+ { MU, A, PCRE2_PARTIAL_SOFT, 0, "(?<=a)b", "a" },+ { MU, A, PCRE2_PARTIAL_SOFT, 0, "abc|(?<=xxa)bc", "xxab" },+ { MU, A, PCRE2_PARTIAL_SOFT, 0, "a\\B", "a" },+ { MU, A, PCRE2_PARTIAL_HARD, 0, "a\\b", "a" },++ /* (*MARK) verb. */+ { MU, A, 0, 0, "a(*MARK:aa)a", "ababaa" },+ { MU, A, 0, 0 | F_NOMATCH, "a(*:aa)a", "abab" },+ { MU, A, 0, 0, "a(*:aa)(b(*:bb)b|bc)", "abc" },+ { MU, A, 0, 0 | F_NOMATCH, "a(*:1)x|b(*:2)y", "abc" },+ { MU, A, 0, 0, "(?>a(*:aa))b|ac", "ac" },+ { MU, A, 0, 0, "(?(DEFINE)(a(*:aa)))(?1)", "a" },+ { MU, A, 0, 0 | F_NOMATCH, "(?(DEFINE)((a)(*:aa)))(?1)b", "aa" },+ { MU, A, 0, 0, "(?(DEFINE)(a(*:aa)))a(?1)b|aac", "aac" },+ { MU, A, 0, 0, "(a(*:aa)){0}(?:b(?1)b|c)+c", "babbab cc" },+ { MU, A, 0, 0, "(a(*:aa)){0}(?:b(?1)b)+", "babba" },+ { MU, A, 0, 0 | F_NOMATCH, "(a(*:aa)){0}(?:b(?1)b)+", "ba" },+ { MU, A, 0, 0, "(a\\K(*:aa)){0}(?:b(?1)b|c)+c", "babbab cc" },+ { MU, A, 0, 0, "(a\\K(*:aa)){0}(?:b(?1)b)+", "babba" },+ { MU, A, 0, 0 | F_NOMATCH, "(a\\K(*:aa)){0}(?:b(?1)b)+", "ba" },+ { MU, A, 0, 0 | F_NOMATCH, "(*:mark)m", "a" },++ /* (*COMMIT) verb. */+ { MU, A, 0, 0 | F_NOMATCH, "a(*COMMIT)b", "ac" },+ { MU, A, 0, 0, "aa(*COMMIT)b", "xaxaab" },+ { MU, A, 0, 0 | F_NOMATCH, "a(*COMMIT)(*:msg)b|ac", "ac" },+ { MU, A, 0, 0 | F_NOMATCH, "(a(*COMMIT)b)++", "abac" },+ { MU, A, 0, 0 | F_NOMATCH, "((a)(*COMMIT)b)++", "abac" },+ { MU, A, 0, 0 | F_NOMATCH, "(?=a(*COMMIT)b)ab|ad", "ad" },++ /* (*PRUNE) verb. */+ { MU, A, 0, 0, "aa\\K(*PRUNE)b", "aaab" },+ { MU, A, 0, 0, "aa(*PRUNE:bb)b|a", "aa" },+ { MU, A, 0, 0, "(a)(a)(*PRUNE)b|(a)", "aa" },+ { MU, A, 0, 0, "(a)(a)(a)(a)(a)(a)(a)(a)(*PRUNE)b|(a)", "aaaaaaaa" },+ { MU, A, PCRE2_PARTIAL_SOFT, 0, "a(*PRUNE)a|", "a" },+ { MU, A, PCRE2_PARTIAL_SOFT, 0, "a(*PRUNE)a|m", "a" },+ { MU, A, 0, 0 | F_NOMATCH, "(?=a(*PRUNE)b)ab|ad", "ad" },+ { MU, A, 0, 0, "a(*COMMIT)(*PRUNE)d|bc", "abc" },+ { MU, A, 0, 0, "(?=a(*COMMIT)b)a(*PRUNE)c|bc", "abc" },+ { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?=a(*COMMIT)b)a(*PRUNE)c|bc", "abc" },+ { MU, A, 0, 0, "(?=(a)(*COMMIT)b)a(*PRUNE)c|bc", "abc" },+ { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?=(a)(*COMMIT)b)a(*PRUNE)c|bc", "abc" },+ { MU, A, 0, 0, "(a(*COMMIT)b){0}a(?1)(*PRUNE)c|bc", "abc" },+ { MU, A, 0, 0 | F_NOMATCH, "(a(*COMMIT)b){0}a(*COMMIT)(?1)(*PRUNE)c|bc", "abc" },+ { MU, A, 0, 0, "(a(*COMMIT)b)++(*PRUNE)d|c", "ababc" },+ { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(a(*COMMIT)b)++(*PRUNE)d|c", "ababc" },+ { MU, A, 0, 0, "((a)(*COMMIT)b)++(*PRUNE)d|c", "ababc" },+ { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)((a)(*COMMIT)b)++(*PRUNE)d|c", "ababc" },+ { MU, A, 0, 0, "(?>a(*COMMIT)b)*abab(*PRUNE)d|ba", "ababab" },+ { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)*abab(*PRUNE)d|ba", "ababab" },+ { MU, A, 0, 0, "(?>a(*COMMIT)b)+abab(*PRUNE)d|ba", "ababab" },+ { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)+abab(*PRUNE)d|ba", "ababab" },+ { MU, A, 0, 0, "(?>a(*COMMIT)b)?ab(*PRUNE)d|ba", "aba" },+ { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)?ab(*PRUNE)d|ba", "aba" },+ { MU, A, 0, 0, "(?>a(*COMMIT)b)*?n(*PRUNE)d|ba", "abababn" },+ { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)*?n(*PRUNE)d|ba", "abababn" },+ { MU, A, 0, 0, "(?>a(*COMMIT)b)+?n(*PRUNE)d|ba", "abababn" },+ { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)+?n(*PRUNE)d|ba", "abababn" },+ { MU, A, 0, 0, "(?>a(*COMMIT)b)??n(*PRUNE)d|bn", "abn" },+ { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)??n(*PRUNE)d|bn", "abn" },++ /* (*SKIP) verb. */+ { MU, A, 0, 0 | F_NOMATCH, "(?=a(*SKIP)b)ab|ad", "ad" },+ { MU, A, 0, 0, "(\\w+(*SKIP)#)", "abcd,xyz#," },+ { MU, A, 0, 0, "\\w+(*SKIP)#|mm", "abcd,xyz#," },+ { MU, A, 0, 0 | F_NOMATCH, "b+(?<=(*SKIP)#c)|b+", "#bbb" },++ /* (*THEN) verb. */+ { MU, A, 0, 0, "((?:a(*THEN)|aab)(*THEN)c|a+)+m", "aabcaabcaabcaabcnacm" },+ { MU, A, 0, 0 | F_NOMATCH, "((?:a(*THEN)|aab)(*THEN)c|a+)+m", "aabcm" },+ { MU, A, 0, 0, "((?:a(*THEN)|aab)c|a+)+m", "aabcaabcnmaabcaabcm" },+ { MU, A, 0, 0, "((?:a|aab)(*THEN)c|a+)+m", "aam" },+ { MU, A, 0, 0, "((?:a(*COMMIT)|aab)(*THEN)c|a+)+m", "aam" },+ { MU, A, 0, 0, "(?(?=a(*THEN)b)ab|ad)", "ad" },+ { MU, A, 0, 0, "(?(?!a(*THEN)b)ad|add)", "add" },+ { MU, A, 0, 0 | F_NOMATCH, "(?(?=a)a(*THEN)b|ad)", "ad" },+ { MU, A, 0, 0, "(?!(?(?=a)ab|b(*THEN)d))bn|bnn", "bnn" },+ { MU, A, 0, 0, "(?=(*THEN: ))* ", " " },+ { MU, A, 0, 0, "a(*THEN)(?R) |", "a" },++ /* Recurse and control verbs. */+ { MU, A, 0, 0, "(a(*ACCEPT)b){0}a(?1)b", "aacaabb" },+ { MU, A, 0, 0, "((a)\\2(*ACCEPT)b){0}a(?1)b", "aaacaaabb" },+ { MU, A, 0, 0, "((ab|a(*ACCEPT)x)+|ababababax){0}_(?1)_", "_ababababax_ _ababababa_" },+ { MU, A, 0, 0, "((.)(?:A(*ACCEPT)|(?1)\\2)){0}_(?1)_", "_bcdaAdcb_bcdaAdcb_" },+ { MU, A, 0, 0, "((*MARK:m)(?:a|a(*COMMIT)b|aa)){0}_(?1)_", "_ab_" },+ { MU, A, 0, 0, "((*MARK:m)(?:a|a(*COMMIT)b|aa)){0}_(?1)_|(_aa_)", "_aa_" },+ { MU, A, 0, 0, "(a(*COMMIT)(?:b|bb)|c(*ACCEPT)d|dd){0}_(?1)+_", "_ax_ _cd_ _abbb_ _abcd_ _abbcdd_" },+ { MU, A, 0, 0, "((.)(?:.|(*COMMIT)\\2{3}(*ACCEPT).*|.*)){0}_(?1){0,4}_", "_aaaabbbbccccddd_ _aaaabbbbccccdddd_" },++#ifdef SUPPORT_UNICODE+ /* Script runs and iterations. */+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)*#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)+#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)*?#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)+?#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)*+#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)++#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)?#", "!ab!abc!ab!ab#" },+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)??#", "!ab!abc!ab!ab#" },+#endif++ /* Deep recursion. */+ { MU, A, 0, 0, "((((?:(?:(?:\\w)+)?)*|(?>\\w)+?)+|(?>\\w)?\?)*)?\\s", "aaaaa+ " },+ { MU, A, 0, 0, "(?:((?:(?:(?:\\w*?)+)??|(?>\\w)?|\\w*+)*)+)+?\\s", "aa+ " },+ { MU, A, 0, 0, "((a?)+)+b", "aaaaaaaaaaaa b" },++ /* Deep recursion: Stack limit reached. */+ { M, A, 0, 0 | F_NOMATCH, "a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaa" },+ { M, A, 0, 0 | F_NOMATCH, "(?:a+)+b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },+ { M, A, 0, 0 | F_NOMATCH, "(?:a+?)+?b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },+ { M, A, 0, 0 | F_NOMATCH, "(?:a*)*b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },+ { M, A, 0, 0 | F_NOMATCH, "(?:a*?)*?b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },++ { 0, 0, 0, 0, NULL, NULL }+};++#ifdef SUPPORT_PCRE2_8+static pcre2_jit_stack_8* callback8(void *arg)+{+ return (pcre2_jit_stack_8 *)arg;+}+#endif++#ifdef SUPPORT_PCRE2_16+static pcre2_jit_stack_16* callback16(void *arg)+{+ return (pcre2_jit_stack_16 *)arg;+}+#endif++#ifdef SUPPORT_PCRE2_32+static pcre2_jit_stack_32* callback32(void *arg)+{+ return (pcre2_jit_stack_32 *)arg;+}+#endif++#ifdef SUPPORT_PCRE2_8+static pcre2_jit_stack_8 *stack8;++static pcre2_jit_stack_8 *getstack8(void)+{+ if (!stack8)+ stack8 = pcre2_jit_stack_create_8(1, 1024 * 1024, NULL);+ return stack8;+}++static void setstack8(pcre2_match_context_8 *mcontext)+{+ if (!mcontext) {+ if (stack8)+ pcre2_jit_stack_free_8(stack8);+ stack8 = NULL;+ return;+ }++ pcre2_jit_stack_assign_8(mcontext, callback8, getstack8());+}+#endif /* SUPPORT_PCRE2_8 */++#ifdef SUPPORT_PCRE2_16+static pcre2_jit_stack_16 *stack16;++static pcre2_jit_stack_16 *getstack16(void)+{+ if (!stack16)+ stack16 = pcre2_jit_stack_create_16(1, 1024 * 1024, NULL);+ return stack16;+}++static void setstack16(pcre2_match_context_16 *mcontext)+{+ if (!mcontext) {+ if (stack16)+ pcre2_jit_stack_free_16(stack16);+ stack16 = NULL;+ return;+ }++ pcre2_jit_stack_assign_16(mcontext, callback16, getstack16());+}+#endif /* SUPPORT_PCRE2_16 */++#ifdef SUPPORT_PCRE2_32+static pcre2_jit_stack_32 *stack32;++static pcre2_jit_stack_32 *getstack32(void)+{+ if (!stack32)+ stack32 = pcre2_jit_stack_create_32(1, 1024 * 1024, NULL);+ return stack32;+}++static void setstack32(pcre2_match_context_32 *mcontext)+{+ if (!mcontext) {+ if (stack32)+ pcre2_jit_stack_free_32(stack32);+ stack32 = NULL;+ return;+ }++ pcre2_jit_stack_assign_32(mcontext, callback32, getstack32());+}+#endif /* SUPPORT_PCRE2_32 */++#ifdef SUPPORT_PCRE2_16++static int convert_utf8_to_utf16(PCRE2_SPTR8 input, PCRE2_UCHAR16 *output, int *offsetmap, int max_length)+{+ PCRE2_SPTR8 iptr = input;+ PCRE2_UCHAR16 *optr = output;+ unsigned int c;++ if (max_length == 0)+ return 0;++ while (*iptr && max_length > 1) {+ c = 0;+ if (offsetmap)+ *offsetmap++ = (int)(iptr - (unsigned char*)input);++ if (*iptr < 0xc0)+ c = *iptr++;+ else if (!(*iptr & 0x20)) {+ c = ((iptr[0] & 0x1f) << 6) | (iptr[1] & 0x3f);+ iptr += 2;+ } else if (!(*iptr & 0x10)) {+ c = ((iptr[0] & 0x0f) << 12) | ((iptr[1] & 0x3f) << 6) | (iptr[2] & 0x3f);+ iptr += 3;+ } else if (!(*iptr & 0x08)) {+ c = ((iptr[0] & 0x07) << 18) | ((iptr[1] & 0x3f) << 12) | ((iptr[2] & 0x3f) << 6) | (iptr[3] & 0x3f);+ iptr += 4;+ }++ if (c < 65536) {+ *optr++ = c;+ max_length--;+ } else if (max_length <= 2) {+ *optr = '\0';+ return (int)(optr - output);+ } else {+ c -= 0x10000;+ *optr++ = 0xd800 | ((c >> 10) & 0x3ff);+ *optr++ = 0xdc00 | (c & 0x3ff);+ max_length -= 2;+ if (offsetmap)+ offsetmap++;+ }+ }+ if (offsetmap)+ *offsetmap = (int)(iptr - (unsigned char*)input);+ *optr = '\0';+ return (int)(optr - output);+}++static int copy_char8_to_char16(PCRE2_SPTR8 input, PCRE2_UCHAR16 *output, int max_length)+{+ PCRE2_SPTR8 iptr = input;+ PCRE2_UCHAR16 *optr = output;++ if (max_length == 0)+ return 0;++ while (*iptr && max_length > 1) {+ *optr++ = *iptr++;+ max_length--;+ }+ *optr = '\0';+ return (int)(optr - output);+}++#define REGTEST_MAX_LENGTH16 4096+static PCRE2_UCHAR16 regtest_buf16[REGTEST_MAX_LENGTH16];+static int regtest_offsetmap16[REGTEST_MAX_LENGTH16];++#endif /* SUPPORT_PCRE2_16 */++#ifdef SUPPORT_PCRE2_32++static int convert_utf8_to_utf32(PCRE2_SPTR8 input, PCRE2_UCHAR32 *output, int *offsetmap, int max_length)+{+ PCRE2_SPTR8 iptr = input;+ PCRE2_UCHAR32 *optr = output;+ unsigned int c;++ if (max_length == 0)+ return 0;++ while (*iptr && max_length > 1) {+ c = 0;+ if (offsetmap)+ *offsetmap++ = (int)(iptr - (unsigned char*)input);++ if (*iptr < 0xc0)+ c = *iptr++;+ else if (!(*iptr & 0x20)) {+ c = ((iptr[0] & 0x1f) << 6) | (iptr[1] & 0x3f);+ iptr += 2;+ } else if (!(*iptr & 0x10)) {+ c = ((iptr[0] & 0x0f) << 12) | ((iptr[1] & 0x3f) << 6) | (iptr[2] & 0x3f);+ iptr += 3;+ } else if (!(*iptr & 0x08)) {+ c = ((iptr[0] & 0x07) << 18) | ((iptr[1] & 0x3f) << 12) | ((iptr[2] & 0x3f) << 6) | (iptr[3] & 0x3f);+ iptr += 4;+ }++ *optr++ = c;+ max_length--;+ }+ if (offsetmap)+ *offsetmap = (int)(iptr - (unsigned char*)input);+ *optr = 0;+ return (int)(optr - output);+}++static int copy_char8_to_char32(PCRE2_SPTR8 input, PCRE2_UCHAR32 *output, int max_length)+{+ PCRE2_SPTR8 iptr = input;+ PCRE2_UCHAR32 *optr = output;++ if (max_length == 0)+ return 0;++ while (*iptr && max_length > 1) {+ *optr++ = *iptr++;+ max_length--;+ }+ *optr = '\0';+ return (int)(optr - output);+}++#define REGTEST_MAX_LENGTH32 4096+static PCRE2_UCHAR32 regtest_buf32[REGTEST_MAX_LENGTH32];+static int regtest_offsetmap32[REGTEST_MAX_LENGTH32];++#endif /* SUPPORT_PCRE2_32 */++static int check_ascii(const char *input)+{+ const unsigned char *ptr = (unsigned char *)input;+ while (*ptr) {+ if (*ptr > 127)+ return 0;+ ptr++;+ }+ return 1;+}++#define OVECTOR_SIZE 15++static int regression_tests(void)+{+ struct regression_test_case *current = regression_test_cases;+ int error;+ PCRE2_SIZE err_offs;+ int is_successful;+ int is_ascii;+ int total = 0;+ int successful = 0;+ int successful_row = 0;+ int counter = 0;+ int jit_compile_mode;+ int utf = 0;+ int disabled_options = 0;+ int i;+#ifdef SUPPORT_PCRE2_8+ pcre2_code_8 *re8;+ pcre2_compile_context_8 *ccontext8;+ pcre2_match_data_8 *mdata8_1;+ pcre2_match_data_8 *mdata8_2;+ pcre2_match_context_8 *mcontext8;+ PCRE2_SIZE *ovector8_1 = NULL;+ PCRE2_SIZE *ovector8_2 = NULL;+ int return_value8[2];+#endif+#ifdef SUPPORT_PCRE2_16+ pcre2_code_16 *re16;+ pcre2_compile_context_16 *ccontext16;+ pcre2_match_data_16 *mdata16_1;+ pcre2_match_data_16 *mdata16_2;+ pcre2_match_context_16 *mcontext16;+ PCRE2_SIZE *ovector16_1 = NULL;+ PCRE2_SIZE *ovector16_2 = NULL;+ int return_value16[2];+ int length16;+#endif+#ifdef SUPPORT_PCRE2_32+ pcre2_code_32 *re32;+ pcre2_compile_context_32 *ccontext32;+ pcre2_match_data_32 *mdata32_1;+ pcre2_match_data_32 *mdata32_2;+ pcre2_match_context_32 *mcontext32;+ PCRE2_SIZE *ovector32_1 = NULL;+ PCRE2_SIZE *ovector32_2 = NULL;+ int return_value32[2];+ int length32;+#endif++#if defined SUPPORT_PCRE2_8+ PCRE2_UCHAR8 cpu_info[128];+#elif defined SUPPORT_PCRE2_16+ PCRE2_UCHAR16 cpu_info[128];+#elif defined SUPPORT_PCRE2_32+ PCRE2_UCHAR32 cpu_info[128];+#endif+#if defined SUPPORT_UNICODE && ((defined(SUPPORT_PCRE2_8) + defined(SUPPORT_PCRE2_16) + defined(SUPPORT_PCRE2_32)) >= 2)+ int return_value;+#endif++ /* This test compares the behaviour of interpreter and JIT. Although disabling+ utf or ucp may make tests fail, if the pcre_exec result is the SAME, it is+ still considered successful from pcre_jit_test point of view. */++#if defined SUPPORT_PCRE2_8+ pcre2_config_8(PCRE2_CONFIG_JITTARGET, &cpu_info);+#elif defined SUPPORT_PCRE2_16+ pcre2_config_16(PCRE2_CONFIG_JITTARGET, &cpu_info);+#elif defined SUPPORT_PCRE2_32+ pcre2_config_32(PCRE2_CONFIG_JITTARGET, &cpu_info);+#endif++ printf("Running JIT regression tests\n");+ printf(" target CPU of SLJIT compiler: ");+ for (i = 0; cpu_info[i]; i++)+ printf("%c", (char)(cpu_info[i]));+ printf("\n");++#if defined SUPPORT_PCRE2_8+ pcre2_config_8(PCRE2_CONFIG_UNICODE, &utf);+#elif defined SUPPORT_PCRE2_16+ pcre2_config_16(PCRE2_CONFIG_UNICODE, &utf);+#elif defined SUPPORT_PCRE2_32+ pcre2_config_32(PCRE2_CONFIG_UNICODE, &utf);+#endif++ if (!utf)+ disabled_options |= PCRE2_UTF;+#ifdef SUPPORT_PCRE2_8+ printf(" in 8 bit mode with UTF-8 %s:\n", utf ? "enabled" : "disabled");+#endif+#ifdef SUPPORT_PCRE2_16+ printf(" in 16 bit mode with UTF-16 %s:\n", utf ? "enabled" : "disabled");+#endif+#ifdef SUPPORT_PCRE2_32+ printf(" in 32 bit mode with UTF-32 %s:\n", utf ? "enabled" : "disabled");+#endif++ while (current->pattern) {+ /* printf("\nPattern: %s :\n", current->pattern); */+ total++;+ is_ascii = 0;+ if (!(current->start_offset & F_PROPERTY))+ is_ascii = check_ascii(current->pattern) && check_ascii(current->input);++ if (current->match_options & PCRE2_PARTIAL_SOFT)+ jit_compile_mode = PCRE2_JIT_PARTIAL_SOFT;+ else if (current->match_options & PCRE2_PARTIAL_HARD)+ jit_compile_mode = PCRE2_JIT_PARTIAL_HARD;+ else+ jit_compile_mode = PCRE2_JIT_COMPLETE;+ error = 0;+#ifdef SUPPORT_PCRE2_8+ re8 = NULL;+ ccontext8 = pcre2_compile_context_create_8(NULL);+ if (ccontext8) {+ if (GET_NEWLINE(current->newline))+ pcre2_set_newline_8(ccontext8, GET_NEWLINE(current->newline));+ if (GET_BSR(current->newline))+ pcre2_set_bsr_8(ccontext8, GET_BSR(current->newline));++ if (!(current->start_offset & F_NO8)) {+ re8 = pcre2_compile_8((PCRE2_SPTR8)current->pattern, PCRE2_ZERO_TERMINATED,+ current->compile_options & ~disabled_options,+ &error, &err_offs, ccontext8);++ if (!re8 && (utf || is_ascii))+ printf("\n8 bit: Cannot compile pattern \"%s\": %d\n", current->pattern, error);+ }+ pcre2_compile_context_free_8(ccontext8);+ }+ else+ printf("\n8 bit: Cannot allocate compile context\n");+#endif+#ifdef SUPPORT_PCRE2_16+ if ((current->compile_options & PCRE2_UTF) || (current->start_offset & F_FORCECONV))+ convert_utf8_to_utf16((PCRE2_SPTR8)current->pattern, regtest_buf16, NULL, REGTEST_MAX_LENGTH16);+ else+ copy_char8_to_char16((PCRE2_SPTR8)current->pattern, regtest_buf16, REGTEST_MAX_LENGTH16);++ re16 = NULL;+ ccontext16 = pcre2_compile_context_create_16(NULL);+ if (ccontext16) {+ if (GET_NEWLINE(current->newline))+ pcre2_set_newline_16(ccontext16, GET_NEWLINE(current->newline));+ if (GET_BSR(current->newline))+ pcre2_set_bsr_16(ccontext16, GET_BSR(current->newline));++ if (!(current->start_offset & F_NO16)) {+ re16 = pcre2_compile_16(regtest_buf16, PCRE2_ZERO_TERMINATED,+ current->compile_options & ~disabled_options,+ &error, &err_offs, ccontext16);++ if (!re16 && (utf || is_ascii))+ printf("\n16 bit: Cannot compile pattern \"%s\": %d\n", current->pattern, error);+ }+ pcre2_compile_context_free_16(ccontext16);+ }+ else+ printf("\n16 bit: Cannot allocate compile context\n");+#endif+#ifdef SUPPORT_PCRE2_32+ if ((current->compile_options & PCRE2_UTF) || (current->start_offset & F_FORCECONV))+ convert_utf8_to_utf32((PCRE2_SPTR8)current->pattern, regtest_buf32, NULL, REGTEST_MAX_LENGTH32);+ else+ copy_char8_to_char32((PCRE2_SPTR8)current->pattern, regtest_buf32, REGTEST_MAX_LENGTH32);++ re32 = NULL;+ ccontext32 = pcre2_compile_context_create_32(NULL);+ if (ccontext32) {+ if (GET_NEWLINE(current->newline))+ pcre2_set_newline_32(ccontext32, GET_NEWLINE(current->newline));+ if (GET_BSR(current->newline))+ pcre2_set_bsr_32(ccontext32, GET_BSR(current->newline));++ if (!(current->start_offset & F_NO32)) {+ re32 = pcre2_compile_32(regtest_buf32, PCRE2_ZERO_TERMINATED,+ current->compile_options & ~disabled_options,+ &error, &err_offs, ccontext32);++ if (!re32 && (utf || is_ascii))+ printf("\n32 bit: Cannot compile pattern \"%s\": %d\n", current->pattern, error);+ }+ pcre2_compile_context_free_32(ccontext32);+ }+ else+ printf("\n32 bit: Cannot allocate compile context\n");+#endif++ counter++;+ if ((counter & 0x3) != 0) {+#ifdef SUPPORT_PCRE2_8+ setstack8(NULL);+#endif+#ifdef SUPPORT_PCRE2_16+ setstack16(NULL);+#endif+#ifdef SUPPORT_PCRE2_32+ setstack32(NULL);+#endif+ }++#ifdef SUPPORT_PCRE2_8+ return_value8[0] = -1000;+ return_value8[1] = -1000;+ mdata8_1 = pcre2_match_data_create_8(OVECTOR_SIZE, NULL);+ mdata8_2 = pcre2_match_data_create_8(OVECTOR_SIZE, NULL);+ mcontext8 = pcre2_match_context_create_8(NULL);+ if (!mdata8_1 || !mdata8_2 || !mcontext8) {+ printf("\n8 bit: Cannot allocate match data\n");+ pcre2_match_data_free_8(mdata8_1);+ pcre2_match_data_free_8(mdata8_2);+ pcre2_match_context_free_8(mcontext8);+ pcre2_code_free_8(re8);+ re8 = NULL;+ } else {+ ovector8_1 = pcre2_get_ovector_pointer_8(mdata8_1);+ ovector8_2 = pcre2_get_ovector_pointer_8(mdata8_2);+ for (i = 0; i < OVECTOR_SIZE * 2; ++i)+ ovector8_1[i] = -2;+ for (i = 0; i < OVECTOR_SIZE * 2; ++i)+ ovector8_2[i] = -2;+ pcre2_set_match_limit_8(mcontext8, 10000000);+ }+ if (re8) {+ return_value8[1] = pcre2_match_8(re8, (PCRE2_SPTR8)current->input, strlen(current->input),+ current->start_offset & OFFSET_MASK, current->match_options, mdata8_2, mcontext8);++ if (pcre2_jit_compile_8(re8, jit_compile_mode)) {+ printf("\n8 bit: JIT compiler does not support \"%s\"\n", current->pattern);+ } else if ((counter & 0x1) != 0) {+ setstack8(mcontext8);+ return_value8[0] = pcre2_match_8(re8, (PCRE2_SPTR8)current->input, strlen(current->input),+ current->start_offset & OFFSET_MASK, current->match_options, mdata8_1, mcontext8);+ } else {+ pcre2_jit_stack_assign_8(mcontext8, NULL, getstack8());+ return_value8[0] = pcre2_jit_match_8(re8, (PCRE2_SPTR8)current->input, strlen(current->input),+ current->start_offset & OFFSET_MASK, current->match_options, mdata8_1, mcontext8);+ }+ }+#endif++#ifdef SUPPORT_PCRE2_16+ return_value16[0] = -1000;+ return_value16[1] = -1000;+ mdata16_1 = pcre2_match_data_create_16(OVECTOR_SIZE, NULL);+ mdata16_2 = pcre2_match_data_create_16(OVECTOR_SIZE, NULL);+ mcontext16 = pcre2_match_context_create_16(NULL);+ if (!mdata16_1 || !mdata16_2 || !mcontext16) {+ printf("\n16 bit: Cannot allocate match data\n");+ pcre2_match_data_free_16(mdata16_1);+ pcre2_match_data_free_16(mdata16_2);+ pcre2_match_context_free_16(mcontext16);+ pcre2_code_free_16(re16);+ re16 = NULL;+ } else {+ ovector16_1 = pcre2_get_ovector_pointer_16(mdata16_1);+ ovector16_2 = pcre2_get_ovector_pointer_16(mdata16_2);+ for (i = 0; i < OVECTOR_SIZE * 2; ++i)+ ovector16_1[i] = -2;+ for (i = 0; i < OVECTOR_SIZE * 2; ++i)+ ovector16_2[i] = -2;+ pcre2_set_match_limit_16(mcontext16, 10000000);+ }+ if (re16) {+ if ((current->compile_options & PCRE2_UTF) || (current->start_offset & F_FORCECONV))+ length16 = convert_utf8_to_utf16((PCRE2_SPTR8)current->input, regtest_buf16, regtest_offsetmap16, REGTEST_MAX_LENGTH16);+ else+ length16 = copy_char8_to_char16((PCRE2_SPTR8)current->input, regtest_buf16, REGTEST_MAX_LENGTH16);++ return_value16[1] = pcre2_match_16(re16, regtest_buf16, length16,+ current->start_offset & OFFSET_MASK, current->match_options, mdata16_2, mcontext16);++ if (pcre2_jit_compile_16(re16, jit_compile_mode)) {+ printf("\n16 bit: JIT compiler does not support \"%s\"\n", current->pattern);+ } else if ((counter & 0x1) != 0) {+ setstack16(mcontext16);+ return_value16[0] = pcre2_match_16(re16, regtest_buf16, length16,+ current->start_offset & OFFSET_MASK, current->match_options, mdata16_1, mcontext16);+ } else {+ pcre2_jit_stack_assign_16(mcontext16, NULL, getstack16());+ return_value16[0] = pcre2_jit_match_16(re16, regtest_buf16, length16,+ current->start_offset & OFFSET_MASK, current->match_options, mdata16_1, mcontext16);+ }+ }+#endif++#ifdef SUPPORT_PCRE2_32+ return_value32[0] = -1000;+ return_value32[1] = -1000;+ mdata32_1 = pcre2_match_data_create_32(OVECTOR_SIZE, NULL);+ mdata32_2 = pcre2_match_data_create_32(OVECTOR_SIZE, NULL);+ mcontext32 = pcre2_match_context_create_32(NULL);+ if (!mdata32_1 || !mdata32_2 || !mcontext32) {+ printf("\n32 bit: Cannot allocate match data\n");+ pcre2_match_data_free_32(mdata32_1);+ pcre2_match_data_free_32(mdata32_2);+ pcre2_match_context_free_32(mcontext32);+ pcre2_code_free_32(re32);+ re32 = NULL;+ } else {+ ovector32_1 = pcre2_get_ovector_pointer_32(mdata32_1);+ ovector32_2 = pcre2_get_ovector_pointer_32(mdata32_2);+ for (i = 0; i < OVECTOR_SIZE * 2; ++i)+ ovector32_1[i] = -2;+ for (i = 0; i < OVECTOR_SIZE * 2; ++i)+ ovector32_2[i] = -2;+ pcre2_set_match_limit_32(mcontext32, 10000000);+ }+ if (re32) {+ if ((current->compile_options & PCRE2_UTF) || (current->start_offset & F_FORCECONV))+ length32 = convert_utf8_to_utf32((PCRE2_SPTR8)current->input, regtest_buf32, regtest_offsetmap32, REGTEST_MAX_LENGTH32);+ else+ length32 = copy_char8_to_char32((PCRE2_SPTR8)current->input, regtest_buf32, REGTEST_MAX_LENGTH32);++ return_value32[1] = pcre2_match_32(re32, regtest_buf32, length32,+ current->start_offset & OFFSET_MASK, current->match_options, mdata32_2, mcontext32);++ if (pcre2_jit_compile_32(re32, jit_compile_mode)) {+ printf("\n32 bit: JIT compiler does not support \"%s\"\n", current->pattern);+ } else if ((counter & 0x1) != 0) {+ setstack32(mcontext32);+ return_value32[0] = pcre2_match_32(re32, regtest_buf32, length32,+ current->start_offset & OFFSET_MASK, current->match_options, mdata32_1, mcontext32);+ } else {+ pcre2_jit_stack_assign_32(mcontext32, NULL, getstack32());+ return_value32[0] = pcre2_jit_match_32(re32, regtest_buf32, length32,+ current->start_offset & OFFSET_MASK, current->match_options, mdata32_1, mcontext32);+ }+ }+#endif++ /* printf("[%d-%d-%d|%d-%d|%d-%d|%d-%d]%s",+ return_value8[0], return_value16[0], return_value32[0],+ (int)ovector8_1[0], (int)ovector8_1[1],+ (int)ovector16_1[0], (int)ovector16_1[1],+ (int)ovector32_1[0], (int)ovector32_1[1],+ (current->compile_options & PCRE2_CASELESS) ? "C" : ""); */++ /* If F_DIFF is set, just run the test, but do not compare the results.+ Segfaults can still be captured. */++ is_successful = 1;+ if (!(current->start_offset & F_DIFF)) {+#if defined SUPPORT_UNICODE && ((defined(SUPPORT_PCRE2_8) + defined(SUPPORT_PCRE2_16) + defined(SUPPORT_PCRE2_32)) >= 2)+ if (!(current->start_offset & F_FORCECONV)) {++ /* All results must be the same. */+#ifdef SUPPORT_PCRE2_8+ if ((return_value = return_value8[0]) != return_value8[1]) {+ printf("\n8 bit: Return value differs(J8:%d,I8:%d): [%d] '%s' @ '%s'\n",+ return_value8[0], return_value8[1], total, current->pattern, current->input);+ is_successful = 0;+ } else+#endif+#ifdef SUPPORT_PCRE2_16+ if ((return_value = return_value16[0]) != return_value16[1]) {+ printf("\n16 bit: Return value differs(J16:%d,I16:%d): [%d] '%s' @ '%s'\n",+ return_value16[0], return_value16[1], total, current->pattern, current->input);+ is_successful = 0;+ } else+#endif+#ifdef SUPPORT_PCRE2_32+ if ((return_value = return_value32[0]) != return_value32[1]) {+ printf("\n32 bit: Return value differs(J32:%d,I32:%d): [%d] '%s' @ '%s'\n",+ return_value32[0], return_value32[1], total, current->pattern, current->input);+ is_successful = 0;+ } else+#endif+#if defined SUPPORT_PCRE2_8 && defined SUPPORT_PCRE2_16+ if (return_value8[0] != return_value16[0]) {+ printf("\n8 and 16 bit: Return value differs(J8:%d,J16:%d): [%d] '%s' @ '%s'\n",+ return_value8[0], return_value16[0],+ total, current->pattern, current->input);+ is_successful = 0;+ } else+#endif+#if defined SUPPORT_PCRE2_8 && defined SUPPORT_PCRE2_32+ if (return_value8[0] != return_value32[0]) {+ printf("\n8 and 32 bit: Return value differs(J8:%d,J32:%d): [%d] '%s' @ '%s'\n",+ return_value8[0], return_value32[0],+ total, current->pattern, current->input);+ is_successful = 0;+ } else+#endif+#if defined SUPPORT_PCRE2_16 && defined SUPPORT_PCRE2_32+ if (return_value16[0] != return_value32[0]) {+ printf("\n16 and 32 bit: Return value differs(J16:%d,J32:%d): [%d] '%s' @ '%s'\n",+ return_value16[0], return_value32[0],+ total, current->pattern, current->input);+ is_successful = 0;+ } else+#endif+ if (return_value >= 0 || return_value == PCRE2_ERROR_PARTIAL) {+ if (return_value == PCRE2_ERROR_PARTIAL) {+ return_value = 2;+ } else {+ return_value *= 2;+ }+#ifdef SUPPORT_PCRE2_8+ return_value8[0] = return_value;+#endif+#ifdef SUPPORT_PCRE2_16+ return_value16[0] = return_value;+#endif+#ifdef SUPPORT_PCRE2_32+ return_value32[0] = return_value;+#endif+ /* Transform back the results. */+ if (current->compile_options & PCRE2_UTF) {+#ifdef SUPPORT_PCRE2_16+ for (i = 0; i < return_value; ++i) {+ if (ovector16_1[i] != PCRE2_UNSET)+ ovector16_1[i] = regtest_offsetmap16[ovector16_1[i]];+ if (ovector16_2[i] != PCRE2_UNSET)+ ovector16_2[i] = regtest_offsetmap16[ovector16_2[i]];+ }+#endif+#ifdef SUPPORT_PCRE2_32+ for (i = 0; i < return_value; ++i) {+ if (ovector32_1[i] != PCRE2_UNSET)+ ovector32_1[i] = regtest_offsetmap32[ovector32_1[i]];+ if (ovector32_2[i] != PCRE2_UNSET)+ ovector32_2[i] = regtest_offsetmap32[ovector32_2[i]];+ }+#endif+ }++ for (i = 0; i < return_value; ++i) {+#if defined SUPPORT_PCRE2_8 && defined SUPPORT_PCRE2_16+ if (ovector8_1[i] != ovector8_2[i] || ovector8_1[i] != ovector16_1[i] || ovector8_1[i] != ovector16_2[i]) {+ printf("\n8 and 16 bit: Ovector[%d] value differs(J8:%d,I8:%d,J16:%d,I16:%d): [%d] '%s' @ '%s' \n",+ i, (int)ovector8_1[i], (int)ovector8_2[i], (int)ovector16_1[i], (int)ovector16_2[i],+ total, current->pattern, current->input);+ is_successful = 0;+ }+#endif+#if defined SUPPORT_PCRE2_8 && defined SUPPORT_PCRE2_32+ if (ovector8_1[i] != ovector8_2[i] || ovector8_1[i] != ovector32_1[i] || ovector8_1[i] != ovector32_2[i]) {+ printf("\n8 and 32 bit: Ovector[%d] value differs(J8:%d,I8:%d,J32:%d,I32:%d): [%d] '%s' @ '%s' \n",+ i, (int)ovector8_1[i], (int)ovector8_2[i], (int)ovector32_1[i], (int)ovector32_2[i],+ total, current->pattern, current->input);+ is_successful = 0;+ }+#endif+#if defined SUPPORT_PCRE2_16 && defined SUPPORT_PCRE2_32+ if (ovector16_1[i] != ovector16_2[i] || ovector16_1[i] != ovector32_1[i] || ovector16_1[i] != ovector32_2[i]) {+ printf("\n16 and 32 bit: Ovector[%d] value differs(J16:%d,I16:%d,J32:%d,I32:%d): [%d] '%s' @ '%s' \n",+ i, (int)ovector16_1[i], (int)ovector16_2[i], (int)ovector32_1[i], (int)ovector32_2[i],+ total, current->pattern, current->input);+ is_successful = 0;+ }+#endif+ }+ }+ } else+#endif /* more than one of SUPPORT_PCRE2_8, SUPPORT_PCRE2_16 and SUPPORT_PCRE2_32 */+ {+#ifdef SUPPORT_PCRE2_8+ if (return_value8[0] != return_value8[1]) {+ printf("\n8 bit: Return value differs(%d:%d): [%d] '%s' @ '%s'\n",+ return_value8[0], return_value8[1], total, current->pattern, current->input);+ is_successful = 0;+ } else if (return_value8[0] >= 0 || return_value8[0] == PCRE2_ERROR_PARTIAL) {+ if (return_value8[0] == PCRE2_ERROR_PARTIAL)+ return_value8[0] = 2;+ else+ return_value8[0] *= 2;++ for (i = 0; i < return_value8[0]; ++i)+ if (ovector8_1[i] != ovector8_2[i]) {+ printf("\n8 bit: Ovector[%d] value differs(%d:%d): [%d] '%s' @ '%s'\n",+ i, (int)ovector8_1[i], (int)ovector8_2[i], total, current->pattern, current->input);+ is_successful = 0;+ }+ }+#endif++#ifdef SUPPORT_PCRE2_16+ if (return_value16[0] != return_value16[1]) {+ printf("\n16 bit: Return value differs(%d:%d): [%d] '%s' @ '%s'\n",+ return_value16[0], return_value16[1], total, current->pattern, current->input);+ is_successful = 0;+ } else if (return_value16[0] >= 0 || return_value16[0] == PCRE2_ERROR_PARTIAL) {+ if (return_value16[0] == PCRE2_ERROR_PARTIAL)+ return_value16[0] = 2;+ else+ return_value16[0] *= 2;++ for (i = 0; i < return_value16[0]; ++i)+ if (ovector16_1[i] != ovector16_2[i]) {+ printf("\n16 bit: Ovector[%d] value differs(%d:%d): [%d] '%s' @ '%s'\n",+ i, (int)ovector16_1[i], (int)ovector16_2[i], total, current->pattern, current->input);+ is_successful = 0;+ }+ }+#endif++#ifdef SUPPORT_PCRE2_32+ if (return_value32[0] != return_value32[1]) {+ printf("\n32 bit: Return value differs(%d:%d): [%d] '%s' @ '%s'\n",+ return_value32[0], return_value32[1], total, current->pattern, current->input);+ is_successful = 0;+ } else if (return_value32[0] >= 0 || return_value32[0] == PCRE2_ERROR_PARTIAL) {+ if (return_value32[0] == PCRE2_ERROR_PARTIAL)+ return_value32[0] = 2;+ else+ return_value32[0] *= 2;++ for (i = 0; i < return_value32[0]; ++i)+ if (ovector32_1[i] != ovector32_2[i]) {+ printf("\n32 bit: Ovector[%d] value differs(%d:%d): [%d] '%s' @ '%s'\n",+ i, (int)ovector32_1[i], (int)ovector32_2[i], total, current->pattern, current->input);+ is_successful = 0;+ }+ }+#endif+ }+ }++ if (is_successful) {+#ifdef SUPPORT_PCRE2_8+ if (!(current->start_offset & F_NO8) && (utf || is_ascii)) {+ if (return_value8[0] < 0 && !(current->start_offset & F_NOMATCH)) {+ printf("8 bit: Test should match: [%d] '%s' @ '%s'\n",+ total, current->pattern, current->input);+ is_successful = 0;+ }++ if (return_value8[0] >= 0 && (current->start_offset & F_NOMATCH)) {+ printf("8 bit: Test should not match: [%d] '%s' @ '%s'\n",+ total, current->pattern, current->input);+ is_successful = 0;+ }+ }+#endif+#ifdef SUPPORT_PCRE2_16+ if (!(current->start_offset & F_NO16) && (utf || is_ascii)) {+ if (return_value16[0] < 0 && !(current->start_offset & F_NOMATCH)) {+ printf("16 bit: Test should match: [%d] '%s' @ '%s'\n",+ total, current->pattern, current->input);+ is_successful = 0;+ }++ if (return_value16[0] >= 0 && (current->start_offset & F_NOMATCH)) {+ printf("16 bit: Test should not match: [%d] '%s' @ '%s'\n",+ total, current->pattern, current->input);+ is_successful = 0;+ }+ }+#endif+#ifdef SUPPORT_PCRE2_32+ if (!(current->start_offset & F_NO32) && (utf || is_ascii)) {+ if (return_value32[0] < 0 && !(current->start_offset & F_NOMATCH)) {+ printf("32 bit: Test should match: [%d] '%s' @ '%s'\n",+ total, current->pattern, current->input);+ is_successful = 0;+ }++ if (return_value32[0] >= 0 && (current->start_offset & F_NOMATCH)) {+ printf("32 bit: Test should not match: [%d] '%s' @ '%s'\n",+ total, current->pattern, current->input);+ is_successful = 0;+ }+ }+#endif+ }++ if (is_successful) {+#ifdef SUPPORT_PCRE2_8+ if (re8 && !(current->start_offset & F_NO8) && pcre2_get_mark_8(mdata8_1) != pcre2_get_mark_8(mdata8_2)) {+ printf("8 bit: Mark value mismatch: [%d] '%s' @ '%s'\n",+ total, current->pattern, current->input);+ is_successful = 0;+ }+#endif+#ifdef SUPPORT_PCRE2_16+ if (re16 && !(current->start_offset & F_NO16) && pcre2_get_mark_16(mdata16_1) != pcre2_get_mark_16(mdata16_2)) {+ printf("16 bit: Mark value mismatch: [%d] '%s' @ '%s'\n",+ total, current->pattern, current->input);+ is_successful = 0;+ }+#endif+#ifdef SUPPORT_PCRE2_32+ if (re32 && !(current->start_offset & F_NO32) && pcre2_get_mark_32(mdata32_1) != pcre2_get_mark_32(mdata32_2)) {+ printf("32 bit: Mark value mismatch: [%d] '%s' @ '%s'\n",+ total, current->pattern, current->input);+ is_successful = 0;+ }+#endif+ }++#ifdef SUPPORT_PCRE2_8+ pcre2_code_free_8(re8);+ pcre2_match_data_free_8(mdata8_1);+ pcre2_match_data_free_8(mdata8_2);+ pcre2_match_context_free_8(mcontext8);+#endif+#ifdef SUPPORT_PCRE2_16+ pcre2_code_free_16(re16);+ pcre2_match_data_free_16(mdata16_1);+ pcre2_match_data_free_16(mdata16_2);+ pcre2_match_context_free_16(mcontext16);+#endif+#ifdef SUPPORT_PCRE2_32+ pcre2_code_free_32(re32);+ pcre2_match_data_free_32(mdata32_1);+ pcre2_match_data_free_32(mdata32_2);+ pcre2_match_context_free_32(mcontext32);+#endif++ if (is_successful) {+ successful++;+ successful_row++;+ printf(".");+ if (successful_row >= 60) {+ successful_row = 0;+ printf("\n");+ }+ } else+ successful_row = 0;++ fflush(stdout);+ current++;+ }+#ifdef SUPPORT_PCRE2_8+ setstack8(NULL);+#endif+#ifdef SUPPORT_PCRE2_16+ setstack16(NULL);+#endif+#ifdef SUPPORT_PCRE2_32+ setstack32(NULL);+#endif++ if (total == successful) {+ printf("\nAll JIT regression tests are successfully passed.\n");+ return 0;+ } else {+ printf("\nSuccessful test ratio: %d%% (%d failed)\n", successful * 100 / total, total - successful);+ return 1;+ }+}++#if defined SUPPORT_UNICODE++static int check_invalid_utf_result(int pattern_index, const char *type, int result,+ int match_start, int match_end, PCRE2_SIZE *ovector)+{+ if (match_start < 0) {+ if (result != -1) {+ printf("Pattern[%d] %s result is not -1.\n", pattern_index, type);+ return 1;+ }+ return 0;+ }++ if (result <= 0) {+ printf("Pattern[%d] %s result (%d) is not greater than 0.\n", pattern_index, type, result);+ return 1;+ }++ if (ovector[0] != (PCRE2_SIZE)match_start) {+ printf("Pattern[%d] %s ovector[0] is unexpected (%d instead of %d)\n",+ pattern_index, type, (int)ovector[0], match_start);+ return 1;+ }++ if (ovector[1] != (PCRE2_SIZE)match_end) {+ printf("Pattern[%d] %s ovector[1] is unexpected (%d instead of %d)\n",+ pattern_index, type, (int)ovector[1], match_end);+ return 1;+ }++ return 0;+}++#endif /* SUPPORT_UNICODE */++#if defined SUPPORT_UNICODE && defined SUPPORT_PCRE2_8++#define UDA (PCRE2_UTF | PCRE2_DOTALL | PCRE2_ANCHORED)+#define CI (PCRE2_JIT_COMPLETE | PCRE2_JIT_INVALID_UTF)+#define CPI (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_INVALID_UTF)++struct invalid_utf8_regression_test_case {+ int compile_options;+ int jit_compile_options;+ int start_offset;+ int skip_left;+ int skip_right;+ int match_start;+ int match_end;+ const char *pattern[2];+ const char *input;+};++static const char invalid_utf8_newline_cr;++static const struct invalid_utf8_regression_test_case invalid_utf8_regression_test_cases[] = {+ { UDA, CI, 0, 0, 0, 0, 4, { ".", NULL }, "\xf4\x8f\xbf\xbf" },+ { UDA, CI, 0, 0, 0, 0, 4, { ".", NULL }, "\xf0\x90\x80\x80" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf4\x90\x80\x80" },+ { UDA, CI, 0, 0, 1, -1, -1, { ".", NULL }, "\xf4\x8f\xbf\xbf" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf0\x90\x80\x7f" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf0\x90\x80\xc0" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf0\x8f\xbf\xbf" },+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xef\xbf\xbf#" },+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xef\xbf\xbf" },+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xe0\xa0\x80#" },+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xe0\xa0\x80" },+ { UDA, CI, 0, 0, 2, -1, -1, { ".", NULL }, "\xef\xbf\xbf#" },+ { UDA, CI, 0, 0, 1, -1, -1, { ".", NULL }, "\xef\xbf\xbf" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xef\xbf\x7f#" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xef\xbf\xc0" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xe0\x9f\xbf#" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xe0\x9f\xbf" },+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xed\x9f\xbf#" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xed\xa0\x80#" },+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xee\x80\x80#" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xed\xbf\xbf#" },+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xdf\xbf##" },+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xdf\xbf#" },+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xdf\xbf" },+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xc2\x80##" },+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xc2\x80#" },+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xc2\x80" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xe0\x80##" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xdf\xc0##" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xe0\x80" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xdf\xc0" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xc1\xbf##" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xc1\xbf" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\x80###" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\x80" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf8###" },+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf8" },+ { UDA, CI, 0, 0, 0, 0, 1, { ".", NULL }, "\x7f" },++ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "\xf4\x8f\xbf\xbf#" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf4\xa0\x80\x80\xf4\xa0\x80\x80" },+ { UDA, CPI, 4, 1, 1, -1, -1, { "\\B", "\\b" }, "\xf4\x8f\xbf\xbf\xf4\x8f\xbf\xbf" },+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "#\xef\xbf\xbf#" },+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "#\xe0\xa0\x80#" },+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "\xf0\x90\x80\x80#" },+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "\xf3\xbf\xbf\xbf#" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf0\x8f\xbf\xbf\xf0\x8f\xbf\xbf" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf5\x80\x80\x80\xf5\x80\x80\x80" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf4\x90\x80\x80\xf4\x90\x80\x80" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf4\x8f\xbf\xff\xf4\x8f\xbf\xff" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf4\x8f\xff\xbf\xf4\x8f\xff\xbf" },+ { UDA, CPI, 4, 0, 1, -1, -1, { "\\B", "\\b" }, "\xef\x80\x80\x80\xef\x80\x80" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\x80\x80\x80\x80\x80\x80\x80\x80" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "#\xe0\x9f\xbf\xe0\x9f\xbf#" },+ { UDA, CPI, 4, 2, 2, -1, -1, { "\\B", "\\b" }, "#\xe0\xa0\x80\xe0\xa0\x80#" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "#\xf0\x80\x80\xf0\x80\x80#" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "#\xed\xa0\x80\xed\xa0\x80#" },+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "##\xdf\xbf#" },+ { UDA, CPI, 4, 2, 0, 2, 2, { "\\B", NULL }, "##\xdf\xbf#" },+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "##\xc2\x80#" },+ { UDA, CPI, 4, 2, 0, 2, 2, { "\\B", NULL }, "##\xc2\x80#" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "##\xc1\xbf\xc1\xbf##" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "##\xdf\xc0\xdf\xc0##" },+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "##\xe0\x80\xe0\x80##" },++ { UDA, CPI, 3, 0, 0, 3, 3, { "\\B", NULL }, "\xef\xbf\xbf#" },+ { UDA, CPI, 3, 0, 0, 3, 3, { "\\B", NULL }, "\xe0\xa0\x80#" },+ { UDA, CPI, 3, 0, 0, -1, -1, { "\\B", "\\b" }, "\xe0\x9f\xbf\xe0\x9f\xbf" },+ { UDA, CPI, 3, 1, 1, -1, -1, { "\\B", "\\b" }, "\xef\xbf\xbf\xef\xbf\xbf" },+ { UDA, CPI, 3, 0, 1, -1, -1, { "\\B", "\\b" }, "\xdf\x80\x80\xdf\x80" },+ { UDA, CPI, 3, 0, 0, -1, -1, { "\\B", "\\b" }, "\xef\xbf\xff\xef\xbf\xff" },+ { UDA, CPI, 3, 0, 0, -1, -1, { "\\B", "\\b" }, "\xef\xff\xbf\xef\xff\xbf" },+ { UDA, CPI, 3, 0, 0, -1, -1, { "\\B", "\\b" }, "\xed\xbf\xbf\xed\xbf\xbf" },++ { UDA, CPI, 2, 0, 0, 2, 2, { "\\B", NULL }, "\xdf\xbf#" },+ { UDA, CPI, 2, 0, 0, 2, 2, { "\\B", NULL }, "\xc2\x80#" },+ { UDA, CPI, 2, 1, 1, -1, -1, { "\\B", "\\b" }, "\xdf\xbf\xdf\xbf" },+ { UDA, CPI, 2, 0, 0, -1, -1, { "\\B", "\\b" }, "\xc1\xbf\xc1\xbf" },+ { UDA, CPI, 2, 0, 0, -1, -1, { "\\B", "\\b" }, "\xe0\x80\xe0\x80" },+ { UDA, CPI, 2, 0, 0, -1, -1, { "\\B", "\\b" }, "\xdf\xff\xdf\xff" },+ { UDA, CPI, 2, 0, 0, -1, -1, { "\\B", "\\b" }, "\xff\xbf\xff\xbf" },++ { UDA, CPI, 1, 0, 0, 1, 1, { "\\B", NULL }, "\x7f#" },+ { UDA, CPI, 1, 0, 0, 1, 1, { "\\B", NULL }, "\x01#" },+ { UDA, CPI, 1, 0, 0, -1, -1, { "\\B", "\\b" }, "\x80\x80" },+ { UDA, CPI, 1, 0, 0, -1, -1, { "\\B", "\\b" }, "\xb0\xb0" },++ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 2, { "(.)\\1", NULL }, "aA" },+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, -1, -1, { "(.)\\1", NULL }, "a\xff" },+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 4, { "(.)\\1", NULL }, "\xc3\xa1\xc3\x81" },+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 1, -1, -1, { "(.)\\1", NULL }, "\xc3\xa1\xc3\x81" },+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, -1, -1, { "(.)\\1", NULL }, "\xc2\x80\x80" },+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 6, { "(.)\\1", NULL }, "\xe1\xbd\xb8\xe1\xbf\xb8" },+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 1, -1, -1, { "(.)\\1", NULL }, "\xe1\xbd\xb8\xe1\xbf\xb8" },+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 8, { "(.)\\1", NULL }, "\xf0\x90\x90\x80\xf0\x90\x90\xa8" },+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 1, -1, -1, { "(.)\\1", NULL }, "\xf0\x90\x90\x80\xf0\x90\x90\xa8" },++ { UDA, CPI, 0, 0, 0, 0, 1, { "\\X", NULL }, "A" },+ { UDA, CPI, 0, 0, 0, -1, -1, { "\\X", NULL }, "\xff" },+ { UDA, CPI, 0, 0, 0, 0, 2, { "\\X", NULL }, "\xc3\xa1" },+ { UDA, CPI, 0, 0, 1, -1, -1, { "\\X", NULL }, "\xc3\xa1" },+ { UDA, CPI, 0, 0, 0, -1, -1, { "\\X", NULL }, "\xc3\x7f" },+ { UDA, CPI, 0, 0, 0, 0, 3, { "\\X", NULL }, "\xe1\xbd\xb8" },+ { UDA, CPI, 0, 0, 1, -1, -1, { "\\X", NULL }, "\xe1\xbd\xb8" },+ { UDA, CPI, 0, 0, 0, 0, 4, { "\\X", NULL }, "\xf0\x90\x90\x80" },+ { UDA, CPI, 0, 0, 1, -1, -1, { "\\X", NULL }, "\xf0\x90\x90\x80" },++ { UDA, CPI, 0, 0, 0, -1, -1, { "[^#]", NULL }, "#" },+ { UDA, CPI, 0, 0, 0, 0, 4, { "[^#]", NULL }, "\xf4\x8f\xbf\xbf" },+ { UDA, CPI, 0, 0, 0, -1, -1, { "[^#]", NULL }, "\xf4\x90\x80\x80" },+ { UDA, CPI, 0, 0, 0, -1, -1, { "[^#]", NULL }, "\xc1\x80" },++ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 2, 3, { "^\\W", NULL }, " \x0a#"},+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 14, 15, { "^\\W", NULL }, " \xc0\x8a#\xe0\x80\x8a#\xf0\x80\x80\x8a#\x0a#"},+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 3, 4, { "^\\W", NULL }, " \xf8\x0a#"},+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 3, 4, { "^\\W", NULL }, " \xc3\x0a#"},+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 3, 4, { "^\\W", NULL }, " \xf1\x0a#"},+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 4, 5, { "^\\W", NULL }, " \xf2\xbf\x0a#"},+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 5, 6, { "^\\W", NULL }, " \xf2\xbf\xbf\x0a#"},+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 3, 4, { "^\\W", NULL }, " \xef\x0a#"},+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 4, 5, { "^\\W", NULL }, " \xef\xbf\x0a#"},+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 5, 6, { "^\\W", NULL }, " \x85#\xc2\x85#"},+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 7, 8, { "^\\W", NULL }, " \xe2\x80\xf8\xe2\x80\xa8#"},++ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, -1, -1, { "#", NULL }, "\xe2\x80\xf8\xe2\x80\xa8#"},+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, 3, 4, { "#", NULL }, "\xe2\x80\xf8#\xe2\x80\xa8#"},+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, -1, -1, { "#", NULL }, "abcd\xc2\x85#"},+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, 1, 2, { "#", NULL }, "\x85#\xc2\x85#"},+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, 5, 6, { "#", NULL }, "\xef,\x80,\xf8#\x0a"},+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, -1, -1, { "#", NULL }, "\xef,\x80,\xf8\x0a#"},++ { PCRE2_UTF | PCRE2_NO_START_OPTIMIZE, CI, 0, 0, 0, 4, 8, { "#\xc7\x85#", NULL }, "\x80\x80#\xc7#\xc7\x85#" },+ { PCRE2_UTF | PCRE2_NO_START_OPTIMIZE, CI, 0, 0, 0, 7, 11, { "#\xc7\x85#", NULL }, "\x80\x80#\xc7\x80\x80\x80#\xc7\x85#" },+ { PCRE2_UTF, CI, 0, 0, 0, 4, 8, { "#\xc7\x85#", NULL }, "\x80\x80#\xc7#\xc7\x85#" },+ { PCRE2_UTF, CI, 0, 0, 0, 7, 11, { "#\xc7\x85#", NULL }, "\x80\x80#\xc7\x80\x80\x80#\xc7\x85#" },++ { PCRE2_UTF | PCRE2_UCP, CI, 0, 0, 0, -1, -1, { "[\\s]", NULL }, "\xed\xa0\x80" },++ /* These two are not invalid UTF tests, but this infrastructure fits better for them. */+ { 0, PCRE2_JIT_COMPLETE, 0, 0, 1, -1, -1, { "\\X{2}", NULL }, "\r\n\n" },+ { 0, PCRE2_JIT_COMPLETE, 0, 0, 1, -1, -1, { "\\R{2}", NULL }, "\r\n\n" },++ { PCRE2_UTF | PCRE2_MULTILINE, CI, 0, 0, 0, -1, -1, { "^.a", &invalid_utf8_newline_cr }, "\xc3\xa7#a" },++ { 0, 0, 0, 0, 0, 0, 0, { NULL, NULL }, NULL }+};++#undef UDA+#undef CI+#undef CPI++static int run_invalid_utf8_test(const struct invalid_utf8_regression_test_case *current,+ int pattern_index, int i, pcre2_compile_context_8 *ccontext, pcre2_match_data_8 *mdata)+{+ pcre2_code_8 *code;+ int result, errorcode;+ PCRE2_SIZE length, erroroffset;+ PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_8(mdata);++ if (current->pattern[i] == NULL)+ return 1;++ code = pcre2_compile_8((PCRE2_UCHAR8*)current->pattern[i], PCRE2_ZERO_TERMINATED,+ current->compile_options, &errorcode, &erroroffset, ccontext);++ if (!code) {+ printf("Pattern[%d:0] cannot be compiled. Error offset: %d\n", pattern_index, (int)erroroffset);+ return 0;+ }++ if (pcre2_jit_compile_8(code, current->jit_compile_options) != 0) {+ printf("Pattern[%d:0] cannot be compiled by the JIT compiler.\n", pattern_index);+ pcre2_code_free_8(code);+ return 0;+ }++ length = (PCRE2_SIZE)(strlen(current->input) - current->skip_left - current->skip_right);++ if (current->jit_compile_options & PCRE2_JIT_COMPLETE) {+ result = pcre2_jit_match_8(code, (PCRE2_UCHAR8*)(current->input + current->skip_left),+ length, current->start_offset - current->skip_left, 0, mdata, NULL);++ if (check_invalid_utf_result(pattern_index, "match", result, current->match_start, current->match_end, ovector)) {+ pcre2_code_free_8(code);+ return 0;+ }+ }++ if (current->jit_compile_options & PCRE2_JIT_PARTIAL_SOFT) {+ result = pcre2_jit_match_8(code, (PCRE2_UCHAR8*)(current->input + current->skip_left),+ length, current->start_offset - current->skip_left, PCRE2_PARTIAL_SOFT, mdata, NULL);++ if (check_invalid_utf_result(pattern_index, "partial match", result, current->match_start, current->match_end, ovector)) {+ pcre2_code_free_8(code);+ return 0;+ }+ }++ pcre2_code_free_8(code);+ return 1;+}++static int invalid_utf8_regression_tests(void)+{+ const struct invalid_utf8_regression_test_case *current;+ pcre2_compile_context_8 *ccontext;+ pcre2_match_data_8 *mdata;+ int total = 0, successful = 0;+ int result;++ printf("\nRunning invalid-utf8 JIT regression tests\n");++ ccontext = pcre2_compile_context_create_8(NULL);+ pcre2_set_newline_8(ccontext, PCRE2_NEWLINE_ANY);+ mdata = pcre2_match_data_create_8(4, NULL);++ for (current = invalid_utf8_regression_test_cases; current->pattern[0]; current++) {+ /* printf("\nPattern: %s :\n", current->pattern); */+ total++;++ result = 1;+ if (current->pattern[1] != &invalid_utf8_newline_cr)+ {+ if (!run_invalid_utf8_test(current, total - 1, 0, ccontext, mdata))+ result = 0;+ if (!run_invalid_utf8_test(current, total - 1, 1, ccontext, mdata))+ result = 0;+ } else {+ pcre2_set_newline_8(ccontext, PCRE2_NEWLINE_CR);+ if (!run_invalid_utf8_test(current, total - 1, 0, ccontext, mdata))+ result = 0;+ pcre2_set_newline_8(ccontext, PCRE2_NEWLINE_ANY);+ }++ if (result) {+ successful++;+ }++ printf(".");+ if ((total % 60) == 0)+ printf("\n");+ }++ if ((total % 60) != 0)+ printf("\n");++ pcre2_match_data_free_8(mdata);+ pcre2_compile_context_free_8(ccontext);++ if (total == successful) {+ printf("\nAll invalid UTF8 JIT regression tests are successfully passed.\n");+ return 0;+ } else {+ printf("\nInvalid UTF8 successful test ratio: %d%% (%d failed)\n", successful * 100 / total, total - successful);+ return 1;+ }+}++#else /* !SUPPORT_UNICODE || !SUPPORT_PCRE2_8 */++static int invalid_utf8_regression_tests(void)+{+ return 0;+}++#endif /* SUPPORT_UNICODE && SUPPORT_PCRE2_8 */++#if defined SUPPORT_UNICODE && defined SUPPORT_PCRE2_16++#define UDA (PCRE2_UTF | PCRE2_DOTALL | PCRE2_ANCHORED)+#define CI (PCRE2_JIT_COMPLETE | PCRE2_JIT_INVALID_UTF)+#define CPI (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_INVALID_UTF)++struct invalid_utf16_regression_test_case {+ int compile_options;+ int jit_compile_options;+ int start_offset;+ int skip_left;+ int skip_right;+ int match_start;+ int match_end;+ const PCRE2_UCHAR16 *pattern[2];+ const PCRE2_UCHAR16 *input;+};++static PCRE2_UCHAR16 allany16[] = { '.', 0 };+static PCRE2_UCHAR16 non_word_boundary16[] = { '\\', 'B', 0 };+static PCRE2_UCHAR16 word_boundary16[] = { '\\', 'b', 0 };+static PCRE2_UCHAR16 backreference16[] = { '(', '.', ')', '\\', '1', 0 };+static PCRE2_UCHAR16 grapheme16[] = { '\\', 'X', 0 };+static PCRE2_UCHAR16 nothashmark16[] = { '[', '^', '#', ']', 0 };+static PCRE2_UCHAR16 afternl16[] = { '^', '\\', 'W', 0 };+static PCRE2_UCHAR16 generic16[] = { '#', 0xd800, 0xdc00, '#', 0 };+static PCRE2_UCHAR16 test16_1[] = { 0xd7ff, 0xe000, 0xffff, 0x01, '#', 0 };+static PCRE2_UCHAR16 test16_2[] = { 0xd800, 0xdc00, 0xd800, 0xdc00, 0 };+static PCRE2_UCHAR16 test16_3[] = { 0xdbff, 0xdfff, 0xdbff, 0xdfff, 0 };+static PCRE2_UCHAR16 test16_4[] = { 0xd800, 0xdbff, 0xd800, 0xdbff, 0 };+static PCRE2_UCHAR16 test16_5[] = { '#', 0xd800, 0xdc00, '#', 0 };+static PCRE2_UCHAR16 test16_6[] = { 'a', 'A', 0xdc28, 0 };+static PCRE2_UCHAR16 test16_7[] = { 0xd801, 0xdc00, 0xd801, 0xdc28, 0 };+static PCRE2_UCHAR16 test16_8[] = { '#', 0xd800, 0xdc00, 0 };+static PCRE2_UCHAR16 test16_9[] = { ' ', 0x2028, '#', 0 };+static PCRE2_UCHAR16 test16_10[] = { ' ', 0xdc00, 0xd800, 0x2028, '#', 0 };+static PCRE2_UCHAR16 test16_11[] = { 0xdc00, 0xdc00, 0xd800, 0xdc00, 0xdc00, '#', 0xd800, 0xdc00, '#', 0 };+static PCRE2_UCHAR16 test16_12[] = { '#', 0xd800, 0xdc00, 0xd800, '#', 0xd800, 0xdc00, 0xdc00, 0xdc00, '#', 0xd800, 0xdc00, '#', 0 };++static const struct invalid_utf16_regression_test_case invalid_utf16_regression_test_cases[] = {+ { UDA, CI, 0, 0, 0, 0, 1, { allany16, NULL }, test16_1 },+ { UDA, CI, 1, 0, 0, 1, 2, { allany16, NULL }, test16_1 },+ { UDA, CI, 2, 0, 0, 2, 3, { allany16, NULL }, test16_1 },+ { UDA, CI, 3, 0, 0, 3, 4, { allany16, NULL }, test16_1 },+ { UDA, CI, 0, 0, 0, 0, 2, { allany16, NULL }, test16_2 },+ { UDA, CI, 0, 0, 3, -1, -1, { allany16, NULL }, test16_2 },+ { UDA, CI, 1, 0, 0, -1, -1, { allany16, NULL }, test16_2 },+ { UDA, CI, 0, 0, 0, 0, 2, { allany16, NULL }, test16_3 },+ { UDA, CI, 0, 0, 3, -1, -1, { allany16, NULL }, test16_3 },+ { UDA, CI, 1, 0, 0, -1, -1, { allany16, NULL }, test16_3 },++ { UDA, CPI, 1, 0, 0, 1, 1, { non_word_boundary16, NULL }, test16_1 },+ { UDA, CPI, 2, 0, 0, 2, 2, { non_word_boundary16, NULL }, test16_1 },+ { UDA, CPI, 3, 0, 0, 3, 3, { non_word_boundary16, NULL }, test16_1 },+ { UDA, CPI, 4, 0, 0, 4, 4, { non_word_boundary16, NULL }, test16_1 },+ { UDA, CPI, 2, 0, 0, 2, 2, { non_word_boundary16, NULL }, test16_2 },+ { UDA, CPI, 2, 0, 0, 2, 2, { non_word_boundary16, NULL }, test16_3 },+ { UDA, CPI, 2, 1, 1, -1, -1, { non_word_boundary16, word_boundary16 }, test16_2 },+ { UDA, CPI, 2, 1, 1, -1, -1, { non_word_boundary16, word_boundary16 }, test16_3 },+ { UDA, CPI, 2, 0, 0, -1, -1, { non_word_boundary16, word_boundary16 }, test16_4 },+ { UDA, CPI, 2, 0, 0, -1, -1, { non_word_boundary16, word_boundary16 }, test16_5 },++ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 2, { backreference16, NULL }, test16_6 },+ { UDA | PCRE2_CASELESS, CPI, 1, 0, 0, -1, -1, { backreference16, NULL }, test16_6 },+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 4, { backreference16, NULL }, test16_7 },+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 1, -1, -1, { backreference16, NULL }, test16_7 },++ { UDA, CPI, 0, 0, 0, 0, 1, { grapheme16, NULL }, test16_6 },+ { UDA, CPI, 1, 0, 0, 1, 2, { grapheme16, NULL }, test16_6 },+ { UDA, CPI, 2, 0, 0, -1, -1, { grapheme16, NULL }, test16_6 },+ { UDA, CPI, 0, 0, 0, 0, 2, { grapheme16, NULL }, test16_7 },+ { UDA, CPI, 2, 0, 0, 2, 4, { grapheme16, NULL }, test16_7 },+ { UDA, CPI, 1, 0, 0, -1, -1, { grapheme16, NULL }, test16_7 },++ { UDA, CPI, 0, 0, 0, -1, -1, { nothashmark16, NULL }, test16_8 },+ { UDA, CPI, 1, 0, 0, 1, 3, { nothashmark16, NULL }, test16_8 },+ { UDA, CPI, 2, 0, 0, -1, -1, { nothashmark16, NULL }, test16_8 },++ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 2, 3, { afternl16, NULL }, test16_9 },+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 4, 5, { afternl16, NULL }, test16_10 },++ { PCRE2_UTF | PCRE2_NO_START_OPTIMIZE, CI, 0, 0, 0, 5, 9, { generic16, NULL }, test16_11 },+ { PCRE2_UTF | PCRE2_NO_START_OPTIMIZE, CI, 0, 0, 0, 9, 13, { generic16, NULL }, test16_12 },+ { PCRE2_UTF, CI, 0, 0, 0, 5, 9, { generic16, NULL }, test16_11 },+ { PCRE2_UTF, CI, 0, 0, 0, 9, 13, { generic16, NULL }, test16_12 },++ { 0, 0, 0, 0, 0, 0, 0, { NULL, NULL }, NULL }+};++#undef UDA+#undef CI+#undef CPI++static int run_invalid_utf16_test(const struct invalid_utf16_regression_test_case *current,+ int pattern_index, int i, pcre2_compile_context_16 *ccontext, pcre2_match_data_16 *mdata)+{+ pcre2_code_16 *code;+ int result, errorcode;+ PCRE2_SIZE length, erroroffset;+ const PCRE2_UCHAR16 *input;+ PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_16(mdata);++ if (current->pattern[i] == NULL)+ return 1;++ code = pcre2_compile_16(current->pattern[i], PCRE2_ZERO_TERMINATED,+ current->compile_options, &errorcode, &erroroffset, ccontext);++ if (!code) {+ printf("Pattern[%d:0] cannot be compiled. Error offset: %d\n", pattern_index, (int)erroroffset);+ return 0;+ }++ if (pcre2_jit_compile_16(code, current->jit_compile_options) != 0) {+ printf("Pattern[%d:0] cannot be compiled by the JIT compiler.\n", pattern_index);+ pcre2_code_free_16(code);+ return 0;+ }++ input = current->input;+ length = 0;++ while (*input++ != 0)+ length++;++ length -= current->skip_left + current->skip_right;++ if (current->jit_compile_options & PCRE2_JIT_COMPLETE) {+ result = pcre2_jit_match_16(code, (current->input + current->skip_left),+ length, current->start_offset - current->skip_left, 0, mdata, NULL);++ if (check_invalid_utf_result(pattern_index, "match", result, current->match_start, current->match_end, ovector)) {+ pcre2_code_free_16(code);+ return 0;+ }+ }++ if (current->jit_compile_options & PCRE2_JIT_PARTIAL_SOFT) {+ result = pcre2_jit_match_16(code, (current->input + current->skip_left),+ length, current->start_offset - current->skip_left, PCRE2_PARTIAL_SOFT, mdata, NULL);++ if (check_invalid_utf_result(pattern_index, "partial match", result, current->match_start, current->match_end, ovector)) {+ pcre2_code_free_16(code);+ return 0;+ }+ }++ pcre2_code_free_16(code);+ return 1;+}++static int invalid_utf16_regression_tests(void)+{+ const struct invalid_utf16_regression_test_case *current;+ pcre2_compile_context_16 *ccontext;+ pcre2_match_data_16 *mdata;+ int total = 0, successful = 0;+ int result;++ printf("\nRunning invalid-utf16 JIT regression tests\n");++ ccontext = pcre2_compile_context_create_16(NULL);+ pcre2_set_newline_16(ccontext, PCRE2_NEWLINE_ANY);+ mdata = pcre2_match_data_create_16(4, NULL);++ for (current = invalid_utf16_regression_test_cases; current->pattern[0]; current++) {+ /* printf("\nPattern: %s :\n", current->pattern); */+ total++;++ result = 1;+ if (!run_invalid_utf16_test(current, total - 1, 0, ccontext, mdata))+ result = 0;+ if (!run_invalid_utf16_test(current, total - 1, 1, ccontext, mdata))+ result = 0;++ if (result) {+ successful++;+ }++ printf(".");+ if ((total % 60) == 0)+ printf("\n");+ }++ if ((total % 60) != 0)+ printf("\n");++ pcre2_match_data_free_16(mdata);+ pcre2_compile_context_free_16(ccontext);++ if (total == successful) {+ printf("\nAll invalid UTF16 JIT regression tests are successfully passed.\n");+ return 0;+ } else {+ printf("\nInvalid UTF16 successful test ratio: %d%% (%d failed)\n", successful * 100 / total, total - successful);+ return 1;+ }+}++#else /* !SUPPORT_UNICODE || !SUPPORT_PCRE2_16 */++static int invalid_utf16_regression_tests(void)+{+ return 0;+}++#endif /* SUPPORT_UNICODE && SUPPORT_PCRE2_16 */++#if defined SUPPORT_UNICODE && defined SUPPORT_PCRE2_32++#define UDA (PCRE2_UTF | PCRE2_DOTALL | PCRE2_ANCHORED)+#define CI (PCRE2_JIT_COMPLETE | PCRE2_JIT_INVALID_UTF)+#define CPI (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_INVALID_UTF)++struct invalid_utf32_regression_test_case {+ int compile_options;+ int jit_compile_options;+ int start_offset;+ int skip_left;+ int skip_right;+ int match_start;+ int match_end;+ const PCRE2_UCHAR32 *pattern[2];+ const PCRE2_UCHAR32 *input;+};++static PCRE2_UCHAR32 allany32[] = { '.', 0 };+static PCRE2_UCHAR32 non_word_boundary32[] = { '\\', 'B', 0 };+static PCRE2_UCHAR32 word_boundary32[] = { '\\', 'b', 0 };+static PCRE2_UCHAR32 backreference32[] = { '(', '.', ')', '\\', '1', 0 };+static PCRE2_UCHAR32 grapheme32[] = { '\\', 'X', 0 };+static PCRE2_UCHAR32 nothashmark32[] = { '[', '^', '#', ']', 0 };+static PCRE2_UCHAR32 afternl32[] = { '^', '\\', 'W', 0 };+static PCRE2_UCHAR32 test32_1[] = { 0x10ffff, 0x10ffff, 0x110000, 0x110000, 0x10ffff, 0 };+static PCRE2_UCHAR32 test32_2[] = { 0xd7ff, 0xe000, 0xd800, 0xdfff, 0xe000, 0xdfff, 0xd800, 0 };+static PCRE2_UCHAR32 test32_3[] = { 'a', 'A', 0x110000, 0 };+static PCRE2_UCHAR32 test32_4[] = { '#', 0x10ffff, 0x110000, 0 };+static PCRE2_UCHAR32 test32_5[] = { ' ', 0x2028, '#', 0 };+static PCRE2_UCHAR32 test32_6[] = { ' ', 0x110000, 0x2028, '#', 0 };++static const struct invalid_utf32_regression_test_case invalid_utf32_regression_test_cases[] = {+ { UDA, CI, 0, 0, 0, 0, 1, { allany32, NULL }, test32_1 },+ { UDA, CI, 2, 0, 0, -1, -1, { allany32, NULL }, test32_1 },+ { UDA, CI, 0, 0, 0, 0, 1, { allany32, NULL }, test32_2 },+ { UDA, CI, 1, 0, 0, 1, 2, { allany32, NULL }, test32_2 },+ { UDA, CI, 2, 0, 0, -1, -1, { allany32, NULL }, test32_2 },+ { UDA, CI, 3, 0, 0, -1, -1, { allany32, NULL }, test32_2 },++ { UDA, CPI, 1, 0, 0, 1, 1, { non_word_boundary32, NULL }, test32_1 },+ { UDA, CPI, 3, 0, 0, -1, -1, { non_word_boundary32, word_boundary32 }, test32_1 },+ { UDA, CPI, 1, 0, 0, 1, 1, { non_word_boundary32, NULL }, test32_2 },+ { UDA, CPI, 3, 0, 0, -1, -1, { non_word_boundary32, word_boundary32 }, test32_2 },+ { UDA, CPI, 6, 0, 0, -1, -1, { non_word_boundary32, word_boundary32 }, test32_2 },++ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 2, { backreference32, NULL }, test32_3 },+ { UDA | PCRE2_CASELESS, CPI, 1, 0, 0, -1, -1, { backreference32, NULL }, test32_3 },++ { UDA, CPI, 0, 0, 0, 0, 1, { grapheme32, NULL }, test32_1 },+ { UDA, CPI, 2, 0, 0, -1, -1, { grapheme32, NULL }, test32_1 },+ { UDA, CPI, 1, 0, 0, 1, 2, { grapheme32, NULL }, test32_2 },+ { UDA, CPI, 2, 0, 0, -1, -1, { grapheme32, NULL }, test32_2 },+ { UDA, CPI, 3, 0, 0, -1, -1, { grapheme32, NULL }, test32_2 },+ { UDA, CPI, 4, 0, 0, 4, 5, { grapheme32, NULL }, test32_2 },++ { UDA, CPI, 0, 0, 0, -1, -1, { nothashmark32, NULL }, test32_4 },+ { UDA, CPI, 1, 0, 0, 1, 2, { nothashmark32, NULL }, test32_4 },+ { UDA, CPI, 2, 0, 0, -1, -1, { nothashmark32, NULL }, test32_4 },+ { UDA, CPI, 1, 0, 0, 1, 2, { nothashmark32, NULL }, test32_2 },+ { UDA, CPI, 2, 0, 0, -1, -1, { nothashmark32, NULL }, test32_2 },++ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 2, 3, { afternl32, NULL }, test32_5 },+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 3, 4, { afternl32, NULL }, test32_6 },++ { 0, 0, 0, 0, 0, 0, 0, { NULL, NULL }, NULL }+};++#undef UDA+#undef CI+#undef CPI++static int run_invalid_utf32_test(const struct invalid_utf32_regression_test_case *current,+ int pattern_index, int i, pcre2_compile_context_32 *ccontext, pcre2_match_data_32 *mdata)+{+ pcre2_code_32 *code;+ int result, errorcode;+ PCRE2_SIZE length, erroroffset;+ const PCRE2_UCHAR32 *input;+ PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_32(mdata);++ if (current->pattern[i] == NULL)+ return 1;++ code = pcre2_compile_32(current->pattern[i], PCRE2_ZERO_TERMINATED,+ current->compile_options, &errorcode, &erroroffset, ccontext);++ if (!code) {+ printf("Pattern[%d:0] cannot be compiled. Error offset: %d\n", pattern_index, (int)erroroffset);+ return 0;+ }++ if (pcre2_jit_compile_32(code, current->jit_compile_options) != 0) {+ printf("Pattern[%d:0] cannot be compiled by the JIT compiler.\n", pattern_index);+ pcre2_code_free_32(code);+ return 0;+ }++ input = current->input;+ length = 0;++ while (*input++ != 0)+ length++;++ length -= current->skip_left + current->skip_right;++ if (current->jit_compile_options & PCRE2_JIT_COMPLETE) {+ result = pcre2_jit_match_32(code, (current->input + current->skip_left),+ length, current->start_offset - current->skip_left, 0, mdata, NULL);++ if (check_invalid_utf_result(pattern_index, "match", result, current->match_start, current->match_end, ovector)) {+ pcre2_code_free_32(code);+ return 0;+ }+ }++ if (current->jit_compile_options & PCRE2_JIT_PARTIAL_SOFT) {+ result = pcre2_jit_match_32(code, (current->input + current->skip_left),+ length, current->start_offset - current->skip_left, PCRE2_PARTIAL_SOFT, mdata, NULL);++ if (check_invalid_utf_result(pattern_index, "partial match", result, current->match_start, current->match_end, ovector)) {+ pcre2_code_free_32(code);+ return 0;+ }+ }++ pcre2_code_free_32(code);+ return 1;+}++static int invalid_utf32_regression_tests(void)+{+ const struct invalid_utf32_regression_test_case *current;+ pcre2_compile_context_32 *ccontext;+ pcre2_match_data_32 *mdata;+ int total = 0, successful = 0;+ int result;++ printf("\nRunning invalid-utf32 JIT regression tests\n");++ ccontext = pcre2_compile_context_create_32(NULL);+ pcre2_set_newline_32(ccontext, PCRE2_NEWLINE_ANY);+ mdata = pcre2_match_data_create_32(4, NULL);++ for (current = invalid_utf32_regression_test_cases; current->pattern[0]; current++) {+ /* printf("\nPattern: %s :\n", current->pattern); */+ total++;++ result = 1;+ if (!run_invalid_utf32_test(current, total - 1, 0, ccontext, mdata))+ result = 0;+ if (!run_invalid_utf32_test(current, total - 1, 1, ccontext, mdata))+ result = 0;++ if (result) {+ successful++;+ }++ printf(".");+ if ((total % 60) == 0)+ printf("\n");+ }++ if ((total % 60) != 0)+ printf("\n");++ pcre2_match_data_free_32(mdata);+ pcre2_compile_context_free_32(ccontext);++ if (total == successful) {+ printf("\nAll invalid UTF32 JIT regression tests are successfully passed.\n");+ return 0;+ } else {+ printf("\nInvalid UTF32 successful test ratio: %d%% (%d failed)\n", successful * 100 / total, total - successful);+ return 1;+ }+}++#else /* !SUPPORT_UNICODE || !SUPPORT_PCRE2_32 */++static int invalid_utf32_regression_tests(void)+{+ return 0;+}++#endif /* SUPPORT_UNICODE && SUPPORT_PCRE2_32 */++/* End of pcre2_jit_test.c */
+ src/c/pcre2/src/pcre2_maketables.c view
@@ -0,0 +1,163 @@+/*************************************************+* 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) 2016-2020 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.+-----------------------------------------------------------------------------+*/+++/* This module contains the external function pcre2_maketables(), which builds+character tables for PCRE2 in the current locale. The file is compiled on its+own as part of the PCRE2 library. It is also included in the compilation of+pcre2_dftables.c as a freestanding program, in which case the macro+PCRE2_DFTABLES is defined. */++#ifndef PCRE2_DFTABLES /* Compiling the library */+# ifdef HAVE_CONFIG_H+# include "config.h"+# endif+# include "pcre2_internal.h"+#endif++++/*************************************************+* Create PCRE2 character tables *+*************************************************/++/* This function builds a set of character tables for use by PCRE2 and returns+a pointer to them. They are build using the ctype functions, and consequently+their contents will depend upon the current locale setting. When compiled as+part of the library, the store is obtained via a general context malloc, if+supplied, but when PCRE2_DFTABLES is defined (when compiling the pcre2_dftables+freestanding auxiliary program) malloc() is used, and the function has a+different name so as not to clash with the prototype in pcre2.h.++Arguments: none when PCRE2_DFTABLES is defined+ else a PCRE2 general context or NULL+Returns: pointer to the contiguous block of data+ else NULL if memory allocation failed+*/++#ifdef PCRE2_DFTABLES /* Included in freestanding pcre2_dftables program */+static const uint8_t *maketables(void)+{+uint8_t *yield = (uint8_t *)malloc(TABLES_LENGTH);++#else /* Not PCRE2_DFTABLES, that is, compiling the library */+PCRE2_EXP_DEFN const uint8_t * PCRE2_CALL_CONVENTION+pcre2_maketables(pcre2_general_context *gcontext)+{+uint8_t *yield = (uint8_t *)((gcontext != NULL)?+ gcontext->memctl.malloc(TABLES_LENGTH, gcontext->memctl.memory_data) :+ malloc(TABLES_LENGTH));+#endif /* PCRE2_DFTABLES */++int i;+uint8_t *p;++if (yield == NULL) return NULL;+p = yield;++/* First comes the lower casing table */++for (i = 0; i < 256; i++) *p++ = tolower(i);++/* Next the case-flipping table */++for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i);++/* Then the character class tables. Don't try to be clever and save effort on+exclusive ones - in some locales things may be different.++Note that the table for "space" includes everything "isspace" gives, including+VT in the default locale. This makes it work for the POSIX class [:space:].+From PCRE1 release 8.34 and for all PCRE2 releases it is also correct for Perl+space, because Perl added VT at release 5.18.++Note also that it is possible for a character to be alnum or alpha without+being lower or upper, such as "male and female ordinals" (\xAA and \xBA) in the+fr_FR locale (at least under Debian Linux's locales as of 12/2005). So we must+test for alnum specially. */++memset(p, 0, cbit_length);+for (i = 0; i < 256; i++)+ {+ if (isdigit(i)) p[cbit_digit + i/8] |= 1u << (i&7);+ if (isupper(i)) p[cbit_upper + i/8] |= 1u << (i&7);+ if (islower(i)) p[cbit_lower + i/8] |= 1u << (i&7);+ if (isalnum(i)) p[cbit_word + i/8] |= 1u << (i&7);+ if (i == '_') p[cbit_word + i/8] |= 1u << (i&7);+ if (isspace(i)) p[cbit_space + i/8] |= 1u << (i&7);+ if (isxdigit(i)) p[cbit_xdigit + i/8] |= 1u << (i&7);+ if (isgraph(i)) p[cbit_graph + i/8] |= 1u << (i&7);+ if (isprint(i)) p[cbit_print + i/8] |= 1u << (i&7);+ if (ispunct(i)) p[cbit_punct + i/8] |= 1u << (i&7);+ if (iscntrl(i)) p[cbit_cntrl + i/8] |= 1u << (i&7);+ }+p += cbit_length;++/* Finally, the character type table. In this, we used to exclude VT from the+white space chars, because Perl didn't recognize it as such for \s and for+comments within regexes. However, Perl changed at release 5.18, so PCRE1+changed at release 8.34 and it's always been this way for PCRE2. */++for (i = 0; i < 256; i++)+ {+ int x = 0;+ if (isspace(i)) x += ctype_space;+ if (isalpha(i)) x += ctype_letter;+ if (islower(i)) x += ctype_lcletter;+ if (isdigit(i)) x += ctype_digit;+ if (isalnum(i) || i == '_') x += ctype_word;+ *p++ = x;+ }++return yield;+}++#ifndef PCRE2_DFTABLES /* Compiling the library */+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_maketables_free(pcre2_general_context *gcontext, const uint8_t *tables)+{+ if (gcontext)+ gcontext->memctl.free((void *)tables, gcontext->memctl.memory_data);+ else+ free((void *)tables);+}+#endif++/* End of pcre2_maketables.c */
+ src/c/pcre2/src/pcre2_match.c view
@@ -0,0 +1,7311 @@+/*************************************************+* 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-2020 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 move on past the OP_RECURSE. */++ P->eptr = Feptr;+ P->mark = Fmark;+ 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+BOOL memchr_not_found_first_cu;+BOOL memchr_not_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_not_found_first_cu = FALSE;+memchr_not_found_first_cu2 = FALSE;+#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. In+ 8-bit mode, the use of memchr() gives a big speed up, even though we have+ to call it twice in caseless mode, in order to find the earliest occurrence+ of the character in either of its cases. If a call to memchr() that+ searches the rest of the subject fails to find one case, remember that in+ order not to keep on repeating the search. This can make a huge difference+ when the strings are very long and only one case is present. */++ else+ {+ if (has_first_cu)+ {+ if (first_cu != first_cu2) /* Caseless */+ {+#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 /* 8-bit code units */+ PCRE2_SPTR pp1 = NULL;+ PCRE2_SPTR pp2 = NULL;+ PCRE2_SIZE cu2size = end_subject - start_match;++ if (!memchr_not_found_first_cu)+ {+ pp1 = memchr(start_match, first_cu, end_subject - start_match);+ if (pp1 == NULL) memchr_not_found_first_cu = TRUE;+ else cu2size = pp1 - start_match;+ }++ /* If pp1 is not NULL, we have arranged to search only as far as pp1,+ to see if the other case is earlier, so we can set "not found" only+ when both searches have returned NULL. */++ if (!memchr_not_found_first_cu2)+ {+ pp2 = memchr(start_match, first_cu2, cu2size);+ memchr_not_found_first_cu2 = (pp2 == NULL && pp1 == NULL);+ }++ if (pp1 == NULL)+ start_match = (pp2 == NULL)? end_subject : pp2;+ else+ start_match = (pp2 == NULL || pp1 < pp2)? pp1 : pp2;+#endif+ }++ /* The caseful case */++ 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 */
+ src/c/pcre2/src/pcre2_match_data.c view
@@ -0,0 +1,166 @@+/*************************************************+* 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) 2016-2019 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++#include "pcre2_internal.h"++++/*************************************************+* Create a match data block given ovector size *+*************************************************/++/* A minimum of 1 is imposed on the number of ovector pairs. */++PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION+pcre2_match_data_create(uint32_t oveccount, pcre2_general_context *gcontext)+{+pcre2_match_data *yield;+if (oveccount < 1) oveccount = 1;+yield = PRIV(memctl_malloc)(+ offsetof(pcre2_match_data, ovector) + 2*oveccount*sizeof(PCRE2_SIZE),+ (pcre2_memctl *)gcontext);+if (yield == NULL) return NULL;+yield->oveccount = oveccount;+yield->flags = 0;+return yield;+}++++/*************************************************+* Create a match data block using pattern data *+*************************************************/++/* If no context is supplied, use the memory allocator from the code. */++PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION+pcre2_match_data_create_from_pattern(const pcre2_code *code,+ pcre2_general_context *gcontext)+{+if (gcontext == NULL) gcontext = (pcre2_general_context *)code;+return pcre2_match_data_create(((pcre2_real_code *)code)->top_bracket + 1,+ gcontext);+}++++/*************************************************+* Free a match data block *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_match_data_free(pcre2_match_data *match_data)+{+if (match_data != NULL)+ {+ if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)+ match_data->memctl.free((void *)match_data->subject,+ match_data->memctl.memory_data);+ match_data->memctl.free(match_data, match_data->memctl.memory_data);+ }+}++++/*************************************************+* Get last mark in match *+*************************************************/++PCRE2_EXP_DEFN PCRE2_SPTR PCRE2_CALL_CONVENTION+pcre2_get_mark(pcre2_match_data *match_data)+{+return match_data->mark;+}++++/*************************************************+* Get pointer to ovector *+*************************************************/++PCRE2_EXP_DEFN PCRE2_SIZE * PCRE2_CALL_CONVENTION+pcre2_get_ovector_pointer(pcre2_match_data *match_data)+{+return match_data->ovector;+}++++/*************************************************+* Get number of ovector slots *+*************************************************/++PCRE2_EXP_DEFN uint32_t PCRE2_CALL_CONVENTION+pcre2_get_ovector_count(pcre2_match_data *match_data)+{+return match_data->oveccount;+}++++/*************************************************+* Get starting code unit in match *+*************************************************/++PCRE2_EXP_DEFN PCRE2_SIZE PCRE2_CALL_CONVENTION+pcre2_get_startchar(pcre2_match_data *match_data)+{+return match_data->startchar;+}++++/*************************************************+* Get size of match data block *+*************************************************/++PCRE2_EXP_DEFN PCRE2_SIZE PCRE2_CALL_CONVENTION+pcre2_get_match_data_size(pcre2_match_data *match_data)+{+return offsetof(pcre2_match_data, ovector) ++ 2 * (match_data->oveccount) * sizeof(PCRE2_SIZE);+}++/* End of pcre2_match_data.c */
+ src/c/pcre2/src/pcre2_newline.c view
@@ -0,0 +1,243 @@+/*************************************************+* 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) 2016 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.+-----------------------------------------------------------------------------+*/+++/* This module contains internal functions for testing newlines when more than+one kind of newline is to be recognized. When a newline is found, its length is+returned. In principle, we could implement several newline "types", each+referring to a different set of newline characters. At present, PCRE2 supports+only NLTYPE_FIXED, which gets handled without these functions, NLTYPE_ANYCRLF,+and NLTYPE_ANY. The full list of Unicode newline characters is taken from+http://unicode.org/unicode/reports/tr18/. */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include "pcre2_internal.h"++++/*************************************************+* Check for newline at given position *+*************************************************/++/* This function is called only via the IS_NEWLINE macro, which does so only+when the newline type is NLTYPE_ANY or NLTYPE_ANYCRLF. The case of a fixed+newline (NLTYPE_FIXED) is handled inline. It is guaranteed that the code unit+pointed to by ptr is less than the end of the string.++Arguments:+ ptr pointer to possible newline+ type the newline type+ endptr pointer to the end of the string+ lenptr where to return the length+ utf TRUE if in utf mode++Returns: TRUE or FALSE+*/++BOOL+PRIV(is_newline)(PCRE2_SPTR ptr, uint32_t type, PCRE2_SPTR endptr,+ uint32_t *lenptr, BOOL utf)+{+uint32_t c;++#ifdef SUPPORT_UNICODE+if (utf) { GETCHAR(c, ptr); } else c = *ptr;+#else+(void)utf;+c = *ptr;+#endif /* SUPPORT_UNICODE */++if (type == NLTYPE_ANYCRLF) switch(c)+ {+ case CHAR_LF:+ *lenptr = 1;+ return TRUE;++ case CHAR_CR:+ *lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;+ return TRUE;++ default:+ return FALSE;+ }++/* NLTYPE_ANY */++else switch(c)+ {+#ifdef EBCDIC+ case CHAR_NEL:+#endif+ case CHAR_LF:+ case CHAR_VT:+ case CHAR_FF:+ *lenptr = 1;+ return TRUE;++ case CHAR_CR:+ *lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;+ return TRUE;++#ifndef EBCDIC+#if PCRE2_CODE_UNIT_WIDTH == 8+ case CHAR_NEL:+ *lenptr = utf? 2 : 1;+ return TRUE;++ case 0x2028: /* LS */+ case 0x2029: /* PS */+ *lenptr = 3;+ return TRUE;++#else /* 16-bit or 32-bit code units */+ case CHAR_NEL:+ case 0x2028: /* LS */+ case 0x2029: /* PS */+ *lenptr = 1;+ return TRUE;+#endif+#endif /* Not EBCDIC */++ default:+ return FALSE;+ }+}++++/*************************************************+* Check for newline at previous position *+*************************************************/++/* This function is called only via the WAS_NEWLINE macro, which does so only+when the newline type is NLTYPE_ANY or NLTYPE_ANYCRLF. The case of a fixed+newline (NLTYPE_FIXED) is handled inline. It is guaranteed that the initial+value of ptr is greater than the start of the string that is being processed.++Arguments:+ ptr pointer to possible newline+ type the newline type+ startptr pointer to the start of the string+ lenptr where to return the length+ utf TRUE if in utf mode++Returns: TRUE or FALSE+*/++BOOL+PRIV(was_newline)(PCRE2_SPTR ptr, uint32_t type, PCRE2_SPTR startptr,+ uint32_t *lenptr, BOOL utf)+{+uint32_t c;+ptr--;++#ifdef SUPPORT_UNICODE+if (utf)+ {+ BACKCHAR(ptr);+ GETCHAR(c, ptr);+ }+else c = *ptr;+#else+(void)utf;+c = *ptr;+#endif /* SUPPORT_UNICODE */++if (type == NLTYPE_ANYCRLF) switch(c)+ {+ case CHAR_LF:+ *lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1;+ return TRUE;++ case CHAR_CR:+ *lenptr = 1;+ return TRUE;++ default:+ return FALSE;+ }++/* NLTYPE_ANY */++else switch(c)+ {+ case CHAR_LF:+ *lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1;+ return TRUE;++#ifdef EBCDIC+ case CHAR_NEL:+#endif+ case CHAR_VT:+ case CHAR_FF:+ case CHAR_CR:+ *lenptr = 1;+ return TRUE;++#ifndef EBCDIC+#if PCRE2_CODE_UNIT_WIDTH == 8+ case CHAR_NEL:+ *lenptr = utf? 2 : 1;+ return TRUE;++ case 0x2028: /* LS */+ case 0x2029: /* PS */+ *lenptr = 3;+ return TRUE;++#else /* 16-bit or 32-bit code units */+ case CHAR_NEL:+ case 0x2028: /* LS */+ case 0x2029: /* PS */+ *lenptr = 1;+ return TRUE;+#endif+#endif /* Not EBCDIC */++ default:+ return FALSE;+ }+}++/* End of pcre2_newline.c */
+ src/c/pcre2/src/pcre2_ord2utf.c view
@@ -0,0 +1,120 @@+/*************************************************+* 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) 2016 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.+-----------------------------------------------------------------------------+*/+++/* This file contains a function that converts a Unicode character code point+into a UTF string. The behaviour is different for each code unit width. */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include "pcre2_internal.h"+++/* If SUPPORT_UNICODE is not defined, this function will never be called.+Supply a dummy function because some compilers do not like empty source+modules. */++#ifndef SUPPORT_UNICODE+unsigned int+PRIV(ord2utf)(uint32_t cvalue, PCRE2_UCHAR *buffer)+{+(void)(cvalue);+(void)(buffer);+return 0;+}+#else /* SUPPORT_UNICODE */+++/*************************************************+* Convert code point to UTF *+*************************************************/++/*+Arguments:+ cvalue the character value+ buffer pointer to buffer for result++Returns: number of code units placed in the buffer+*/++unsigned int+PRIV(ord2utf)(uint32_t cvalue, PCRE2_UCHAR *buffer)+{+/* Convert to UTF-8 */++#if PCRE2_CODE_UNIT_WIDTH == 8+int i, j;+for (i = 0; i < PRIV(utf8_table1_size); i++)+ if ((int)cvalue <= PRIV(utf8_table1)[i]) break;+buffer += i;+for (j = i; j > 0; j--)+ {+ *buffer-- = 0x80 | (cvalue & 0x3f);+ cvalue >>= 6;+ }+*buffer = PRIV(utf8_table2)[i] | cvalue;+return i + 1;++/* Convert to UTF-16 */++#elif PCRE2_CODE_UNIT_WIDTH == 16+if (cvalue <= 0xffff)+ {+ *buffer = (PCRE2_UCHAR)cvalue;+ return 1;+ }+cvalue -= 0x10000;+*buffer++ = 0xd800 | (cvalue >> 10);+*buffer = 0xdc00 | (cvalue & 0x3ff);+return 2;++/* Convert to UTF-32 */++#else+*buffer = (PCRE2_UCHAR)cvalue;+return 1;+#endif+}+#endif /* SUPPORT_UNICODE */++/* End of pcre_ord2utf.c */
+ src/c/pcre2/src/pcre2_pattern_info.c view
@@ -0,0 +1,432 @@+/*************************************************+* 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) 2016-2018 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++#include "pcre2_internal.h"+++/*************************************************+* Return info about compiled pattern *+*************************************************/++/*+Arguments:+ code points to compiled code+ what what information is required+ where where to put the information; if NULL, return length++Returns: 0 when data returned+ > 0 when length requested+ < 0 on error or unset value+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_pattern_info(const pcre2_code *code, uint32_t what, void *where)+{+const pcre2_real_code *re = (pcre2_real_code *)code;++if (where == NULL) /* Requests field length */+ {+ switch(what)+ {+ case PCRE2_INFO_ALLOPTIONS:+ case PCRE2_INFO_ARGOPTIONS:+ case PCRE2_INFO_BACKREFMAX:+ case PCRE2_INFO_BSR:+ case PCRE2_INFO_CAPTURECOUNT:+ case PCRE2_INFO_DEPTHLIMIT:+ case PCRE2_INFO_EXTRAOPTIONS:+ case PCRE2_INFO_FIRSTCODETYPE:+ case PCRE2_INFO_FIRSTCODEUNIT:+ case PCRE2_INFO_HASBACKSLASHC:+ case PCRE2_INFO_HASCRORLF:+ case PCRE2_INFO_HEAPLIMIT:+ case PCRE2_INFO_JCHANGED:+ case PCRE2_INFO_LASTCODETYPE:+ case PCRE2_INFO_LASTCODEUNIT:+ case PCRE2_INFO_MATCHEMPTY:+ case PCRE2_INFO_MATCHLIMIT:+ case PCRE2_INFO_MAXLOOKBEHIND:+ case PCRE2_INFO_MINLENGTH:+ case PCRE2_INFO_NAMEENTRYSIZE:+ case PCRE2_INFO_NAMECOUNT:+ case PCRE2_INFO_NEWLINE:+ return sizeof(uint32_t);++ case PCRE2_INFO_FIRSTBITMAP:+ return sizeof(const uint8_t *);++ case PCRE2_INFO_JITSIZE:+ case PCRE2_INFO_SIZE:+ case PCRE2_INFO_FRAMESIZE:+ return sizeof(size_t);++ case PCRE2_INFO_NAMETABLE:+ return sizeof(PCRE2_SPTR);+ }+ }++if (re == NULL) return PCRE2_ERROR_NULL;++/* Check that the first field in the block is the magic number. If it is not,+return with PCRE2_ERROR_BADMAGIC. */++if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;++/* Check that this pattern was compiled in the correct bit mode */++if ((re->flags & (PCRE2_CODE_UNIT_WIDTH/8)) == 0) return PCRE2_ERROR_BADMODE;++switch(what)+ {+ case PCRE2_INFO_ALLOPTIONS:+ *((uint32_t *)where) = re->overall_options;+ break;++ case PCRE2_INFO_ARGOPTIONS:+ *((uint32_t *)where) = re->compile_options;+ break;++ case PCRE2_INFO_BACKREFMAX:+ *((uint32_t *)where) = re->top_backref;+ break;++ case PCRE2_INFO_BSR:+ *((uint32_t *)where) = re->bsr_convention;+ break;++ case PCRE2_INFO_CAPTURECOUNT:+ *((uint32_t *)where) = re->top_bracket;+ break;++ case PCRE2_INFO_DEPTHLIMIT:+ *((uint32_t *)where) = re->limit_depth;+ if (re->limit_depth == UINT32_MAX) return PCRE2_ERROR_UNSET;+ break;++ case PCRE2_INFO_EXTRAOPTIONS:+ *((uint32_t *)where) = re->extra_options;+ break;++ case PCRE2_INFO_FIRSTCODETYPE:+ *((uint32_t *)where) = ((re->flags & PCRE2_FIRSTSET) != 0)? 1 :+ ((re->flags & PCRE2_STARTLINE) != 0)? 2 : 0;+ break;++ case PCRE2_INFO_FIRSTCODEUNIT:+ *((uint32_t *)where) = ((re->flags & PCRE2_FIRSTSET) != 0)?+ re->first_codeunit : 0;+ break;++ case PCRE2_INFO_FIRSTBITMAP:+ *((const uint8_t **)where) = ((re->flags & PCRE2_FIRSTMAPSET) != 0)?+ &(re->start_bitmap[0]) : NULL;+ break;++ case PCRE2_INFO_FRAMESIZE:+ *((size_t *)where) = offsetof(heapframe, ovector) ++ re->top_bracket * 2 * sizeof(PCRE2_SIZE);+ break;++ case PCRE2_INFO_HASBACKSLASHC:+ *((uint32_t *)where) = (re->flags & PCRE2_HASBKC) != 0;+ break;++ case PCRE2_INFO_HASCRORLF:+ *((uint32_t *)where) = (re->flags & PCRE2_HASCRORLF) != 0;+ break;++ case PCRE2_INFO_HEAPLIMIT:+ *((uint32_t *)where) = re->limit_heap;+ if (re->limit_heap == UINT32_MAX) return PCRE2_ERROR_UNSET;+ break;++ case PCRE2_INFO_JCHANGED:+ *((uint32_t *)where) = (re->flags & PCRE2_JCHANGED) != 0;+ break;++ case PCRE2_INFO_JITSIZE:+#ifdef SUPPORT_JIT+ *((size_t *)where) = (re->executable_jit != NULL)?+ PRIV(jit_get_size)(re->executable_jit) : 0;+#else+ *((size_t *)where) = 0;+#endif+ break;++ case PCRE2_INFO_LASTCODETYPE:+ *((uint32_t *)where) = ((re->flags & PCRE2_LASTSET) != 0)? 1 : 0;+ break;++ case PCRE2_INFO_LASTCODEUNIT:+ *((uint32_t *)where) = ((re->flags & PCRE2_LASTSET) != 0)?+ re->last_codeunit : 0;+ break;++ case PCRE2_INFO_MATCHEMPTY:+ *((uint32_t *)where) = (re->flags & PCRE2_MATCH_EMPTY) != 0;+ break;++ case PCRE2_INFO_MATCHLIMIT:+ *((uint32_t *)where) = re->limit_match;+ if (re->limit_match == UINT32_MAX) return PCRE2_ERROR_UNSET;+ break;++ case PCRE2_INFO_MAXLOOKBEHIND:+ *((uint32_t *)where) = re->max_lookbehind;+ break;++ case PCRE2_INFO_MINLENGTH:+ *((uint32_t *)where) = re->minlength;+ break;++ case PCRE2_INFO_NAMEENTRYSIZE:+ *((uint32_t *)where) = re->name_entry_size;+ break;++ case PCRE2_INFO_NAMECOUNT:+ *((uint32_t *)where) = re->name_count;+ break;++ case PCRE2_INFO_NAMETABLE:+ *((PCRE2_SPTR *)where) = (PCRE2_SPTR)((char *)re + sizeof(pcre2_real_code));+ break;++ case PCRE2_INFO_NEWLINE:+ *((uint32_t *)where) = re->newline_convention;+ break;++ case PCRE2_INFO_SIZE:+ *((size_t *)where) = re->blocksize;+ break;++ default: return PCRE2_ERROR_BADOPTION;+ }++return 0;+}++++/*************************************************+* Callout enumerator *+*************************************************/++/*+Arguments:+ code points to compiled code+ callback function called for each callout block+ callout_data user data passed to the callback++Returns: 0 when successfully completed+ < 0 on local error+ != 0 for callback error+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_callout_enumerate(const pcre2_code *code,+ int (*callback)(pcre2_callout_enumerate_block *, void *), void *callout_data)+{+pcre2_real_code *re = (pcre2_real_code *)code;+pcre2_callout_enumerate_block cb;+PCRE2_SPTR cc;+#ifdef SUPPORT_UNICODE+BOOL utf;+#endif++if (re == NULL) return PCRE2_ERROR_NULL;++#ifdef SUPPORT_UNICODE+utf = (re->overall_options & PCRE2_UTF) != 0;+#endif++/* Check that the first field in the block is the magic number. If it is not,+return with PCRE2_ERROR_BADMAGIC. */++if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;++/* Check that this pattern was compiled in the correct bit mode */++if ((re->flags & (PCRE2_CODE_UNIT_WIDTH/8)) == 0) return PCRE2_ERROR_BADMODE;++cb.version = 0;+cc = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code))+ + re->name_count * re->name_entry_size;++while (TRUE)+ {+ int rc;+ switch (*cc)+ {+ case OP_END:+ return 0;++ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ case OP_STAR:+ case OP_MINSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_EXACT:+ case OP_POSSTAR:+ case OP_POSPLUS:+ case OP_POSQUERY:+ case OP_POSUPTO:+ case OP_STARI:+ case OP_MINSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_EXACTI:+ case OP_POSSTARI:+ case OP_POSPLUSI:+ case OP_POSQUERYI:+ case OP_POSUPTOI:+ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTEXACT:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSUPTO:+ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTEXACTI:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSUPTOI:+ cc += PRIV(OP_lengths)[*cc];+#ifdef SUPPORT_UNICODE+ if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEEXACT:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ case OP_TYPEPOSUPTO:+ cc += PRIV(OP_lengths)[*cc];+#ifdef SUPPORT_UNICODE+ if (cc[-1] == OP_PROP || cc[-1] == OP_NOTPROP) cc += 2;+#endif+ break;++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ cc += GET(cc, 1);+ break;+#endif++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ cc += PRIV(OP_lengths)[*cc] + cc[1];+ break;++ case OP_CALLOUT:+ cb.pattern_position = GET(cc, 1);+ cb.next_item_length = GET(cc, 1 + LINK_SIZE);+ cb.callout_number = cc[1 + 2*LINK_SIZE];+ cb.callout_string_offset = 0;+ cb.callout_string_length = 0;+ cb.callout_string = NULL;+ rc = callback(&cb, callout_data);+ if (rc != 0) return rc;+ cc += PRIV(OP_lengths)[*cc];+ break;++ case OP_CALLOUT_STR:+ cb.pattern_position = GET(cc, 1);+ cb.next_item_length = GET(cc, 1 + LINK_SIZE);+ cb.callout_number = 0;+ cb.callout_string_offset = GET(cc, 1 + 3*LINK_SIZE);+ cb.callout_string_length =+ GET(cc, 1 + 2*LINK_SIZE) - (1 + 4*LINK_SIZE) - 2;+ cb.callout_string = cc + (1 + 4*LINK_SIZE) + 1;+ rc = callback(&cb, callout_data);+ if (rc != 0) return rc;+ cc += GET(cc, 1 + 2*LINK_SIZE);+ break;++ default:+ cc += PRIV(OP_lengths)[*cc];+ break;+ }+ }+}++/* End of pcre2_pattern_info.c */
+ src/c/pcre2/src/pcre2_printint.c view
@@ -0,0 +1,836 @@+/*************************************************+* 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) 2016-2019 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.+-----------------------------------------------------------------------------+*/+++/* This module contains a PCRE private debugging function for printing out the+internal form of a compiled regular expression, along with some supporting+local functions. This source file is #included in pcre2test.c at each supported+code unit width, with PCRE2_SUFFIX set appropriately, just like the functions+that comprise the library. It can also optionally be included in+pcre2_compile.c for detailed debugging in error situations. */+++/* Tables of operator names. The same 8-bit table is used for all code unit+widths, so it must be defined only once. The list itself is defined in+pcre2_internal.h, which is #included by pcre2test before this file. */++#ifndef OP_LISTS_DEFINED+static const char *OP_names[] = { OP_NAME_LIST };+#define OP_LISTS_DEFINED+#endif++/* The functions and tables herein must all have mode-dependent names. */++#define OP_lengths PCRE2_SUFFIX(OP_lengths_)+#define get_ucpname PCRE2_SUFFIX(get_ucpname_)+#define pcre2_printint PCRE2_SUFFIX(pcre2_printint_)+#define print_char PCRE2_SUFFIX(print_char_)+#define print_custring PCRE2_SUFFIX(print_custring_)+#define print_custring_bylen PCRE2_SUFFIX(print_custring_bylen_)+#define print_prop PCRE2_SUFFIX(print_prop_)++/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that+the definition is next to the definition of the opcodes in pcre2_internal.h.+The contents of the table are, however, mode-dependent. */++static const uint8_t OP_lengths[] = { OP_LENGTHS };++++/*************************************************+* Print one character from a string *+*************************************************/++/* In UTF mode the character may occupy more than one code unit.++Arguments:+ f file to write to+ ptr pointer to first code unit of the character+ utf TRUE if string is UTF (will be FALSE if UTF is not supported)++Returns: number of additional code units used+*/++static unsigned int+print_char(FILE *f, PCRE2_SPTR ptr, BOOL utf)+{+uint32_t c = *ptr;+BOOL one_code_unit = !utf;++/* If UTF is supported and requested, check for a valid single code unit. */++#ifdef SUPPORT_UNICODE+if (utf)+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ one_code_unit = c < 0x80;+#elif PCRE2_CODE_UNIT_WIDTH == 16+ one_code_unit = (c & 0xfc00) != 0xd800;+#else+ one_code_unit = (c & 0xfffff800u) != 0xd800u;+#endif /* CODE_UNIT_WIDTH */+ }+#endif /* SUPPORT_UNICODE */++/* Handle a valid one-code-unit character at any width. */++if (one_code_unit)+ {+ if (PRINTABLE(c)) fprintf(f, "%c", (char)c);+ else if (c < 0x80) fprintf(f, "\\x%02x", c);+ else fprintf(f, "\\x{%02x}", c);+ return 0;+ }++/* Code for invalid UTF code units and multi-unit UTF characters is different+for each width. If UTF is not supported, control should never get here, but we+need a return statement to keep the compiler happy. */++#ifndef SUPPORT_UNICODE+return 0;+#else++/* Malformed UTF-8 should occur only if the sanity check has been turned off.+Rather than swallow random bytes, just stop if we hit a bad one. Print it with+\X instead of \x as an indication. */++#if PCRE2_CODE_UNIT_WIDTH == 8+if ((c & 0xc0) != 0xc0)+ {+ fprintf(f, "\\X{%x}", c); /* Invalid starting byte */+ return 0;+ }+else+ {+ int i;+ int a = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */+ int s = 6*a;+ c = (c & PRIV(utf8_table3)[a]) << s;+ for (i = 1; i <= a; i++)+ {+ if ((ptr[i] & 0xc0) != 0x80)+ {+ fprintf(f, "\\X{%x}", c); /* Invalid secondary byte */+ return i - 1;+ }+ s -= 6;+ c |= (ptr[i] & 0x3f) << s;+ }+ fprintf(f, "\\x{%x}", c);+ return a;+}+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */++/* UTF-16: rather than swallow a low surrogate, just stop if we hit a bad one.+Print it with \X instead of \x as an indication. */++#if PCRE2_CODE_UNIT_WIDTH == 16+if ((ptr[1] & 0xfc00) != 0xdc00)+ {+ fprintf(f, "\\X{%x}", c);+ return 0;+ }+c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000;+fprintf(f, "\\x{%x}", c);+return 1;+#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */++/* For UTF-32 we get here only for a malformed code unit, which should only+occur if the sanity check has been turned off. Print it with \X instead of \x+as an indication. */++#if PCRE2_CODE_UNIT_WIDTH == 32+fprintf(f, "\\X{%x}", c);+return 0;+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */+#endif /* SUPPORT_UNICODE */+}++++/*************************************************+* Print string as a list of code units *+*************************************************/++/* These take no account of UTF as they always print each individual code unit.+The string is zero-terminated for print_custring(); the length is given for+print_custring_bylen().++Arguments:+ f file to write to+ ptr point to the string+ len length for print_custring_bylen()++Returns: nothing+*/++static void+print_custring(FILE *f, PCRE2_SPTR ptr)+{+while (*ptr != '\0')+ {+ uint32_t c = *ptr++;+ if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);+ }+}++static void+print_custring_bylen(FILE *f, PCRE2_SPTR ptr, PCRE2_UCHAR len)+{+for (; len > 0; len--)+ {+ uint32_t c = *ptr++;+ if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);+ }+}++++/*************************************************+* Find Unicode property name *+*************************************************/++/* When there is no UTF/UCP support, the table of names does not exist. This+function should not be called in such configurations, because a pattern that+tries to use Unicode properties won't compile. Rather than put lots of #ifdefs+into the main code, however, we just put one into this function. */++static const char *+get_ucpname(unsigned int ptype, unsigned int pvalue)+{+#ifdef SUPPORT_UNICODE+int i;+for (i = PRIV(utt_size) - 1; i >= 0; i--)+ {+ if (ptype == PRIV(utt)[i].type && pvalue == PRIV(utt)[i].value) break;+ }+return (i >= 0)? PRIV(utt_names) + PRIV(utt)[i].name_offset : "??";+#else /* No UTF support */+(void)ptype;+(void)pvalue;+return "??";+#endif /* SUPPORT_UNICODE */+}++++/*************************************************+* Print Unicode property value *+*************************************************/++/* "Normal" properties can be printed from tables. The PT_CLIST property is a+pseudo-property that contains a pointer to a list of case-equivalent+characters.++Arguments:+ f file to write to+ code pointer in the compiled code+ before text to print before+ after text to print after++Returns: nothing+*/++static void+print_prop(FILE *f, PCRE2_SPTR code, const char *before, const char *after)+{+if (code[1] != PT_CLIST)+ {+ fprintf(f, "%s%s %s%s", before, OP_names[*code], get_ucpname(code[1],+ code[2]), after);+ }+else+ {+ const char *not = (*code == OP_PROP)? "" : "not ";+ const uint32_t *p = PRIV(ucd_caseless_sets) + code[2];+ fprintf (f, "%s%sclist", before, not);+ while (*p < NOTACHAR) fprintf(f, " %04x", *p++);+ fprintf(f, "%s", after);+ }+}++++/*************************************************+* Print compiled pattern *+*************************************************/++/* The print_lengths flag controls whether offsets and lengths of items are+printed. Lenths can be turned off from pcre2test so that automatic tests on+bytecode can be written that do not depend on the value of LINK_SIZE.++Arguments:+ re a compiled pattern+ f the file to write to+ print_lengths show various lengths++Returns: nothing+*/++static void+pcre2_printint(pcre2_code *re, FILE *f, BOOL print_lengths)+{+PCRE2_SPTR codestart, nametable, code;+uint32_t nesize = re->name_entry_size;+BOOL utf = (re->overall_options & PCRE2_UTF) != 0;++nametable = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));+code = codestart = nametable + re->name_count * re->name_entry_size;++for(;;)+ {+ PCRE2_SPTR ccode;+ uint32_t c;+ int i;+ const char *flag = " ";+ unsigned int extra = 0;++ if (print_lengths)+ fprintf(f, "%3d ", (int)(code - codestart));+ else+ fprintf(f, " ");++ switch(*code)+ {+/* ========================================================================== */+ /* These cases are never obeyed. This is a fudge that causes a compile-+ time error if the vectors OP_names or OP_lengths, which are indexed+ by opcode, are not the correct length. It seems to be the only way to do+ such a check at compile time, as the sizeof() operator does not work in+ the C preprocessor. */++ case OP_TABLE_LENGTH:+ case OP_TABLE_LENGTH ++ ((sizeof(OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) &&+ (sizeof(OP_lengths) == OP_TABLE_LENGTH)):+ return;+/* ========================================================================== */++ case OP_END:+ fprintf(f, " %s\n", OP_names[*code]);+ fprintf(f, "------------------------------------------------------------------\n");+ return;++ case OP_CHAR:+ fprintf(f, " ");+ do+ {+ code++;+ code += 1 + print_char(f, code, utf);+ }+ while (*code == OP_CHAR);+ fprintf(f, "\n");+ continue;++ case OP_CHARI:+ fprintf(f, " /i ");+ do+ {+ code++;+ code += 1 + print_char(f, code, utf);+ }+ while (*code == OP_CHARI);+ fprintf(f, "\n");+ continue;++ case OP_CBRA:+ case OP_CBRAPOS:+ case OP_SCBRA:+ case OP_SCBRAPOS:+ if (print_lengths) fprintf(f, "%3d ", GET(code, 1));+ else fprintf(f, " ");+ fprintf(f, "%s %d", OP_names[*code], GET2(code, 1+LINK_SIZE));+ break;++ case OP_BRA:+ case OP_BRAPOS:+ case OP_SBRA:+ case OP_SBRAPOS:+ case OP_KETRMAX:+ case OP_KETRMIN:+ case OP_KETRPOS:+ case OP_ALT:+ case OP_KET:+ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_COND:+ case OP_SCOND:+ case OP_REVERSE:+ if (print_lengths) fprintf(f, "%3d ", GET(code, 1));+ else fprintf(f, " ");+ fprintf(f, "%s", OP_names[*code]);+ break;++ case OP_CLOSE:+ fprintf(f, " %s %d", OP_names[*code], GET2(code, 1));+ break;++ case OP_CREF:+ fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]);+ break;++ case OP_DNCREF:+ {+ PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;+ fprintf(f, " %s Cond ref <", flag);+ print_custring(f, entry);+ fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));+ }+ break;++ case OP_RREF:+ c = GET2(code, 1);+ if (c == RREF_ANY)+ fprintf(f, " Cond recurse any");+ else+ fprintf(f, " Cond recurse %d", c);+ break;++ case OP_DNRREF:+ {+ PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;+ fprintf(f, " %s Cond recurse <", flag);+ print_custring(f, entry);+ fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));+ }+ break;++ case OP_FALSE:+ fprintf(f, " Cond false");+ break;++ case OP_TRUE:+ fprintf(f, " Cond true");+ break;++ case OP_STARI:+ case OP_MINSTARI:+ case OP_POSSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_POSPLUSI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_POSQUERYI:+ flag = "/i";+ /* Fall through */+ case OP_STAR:+ case OP_MINSTAR:+ case OP_POSSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_POSPLUS:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_POSQUERY:+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEPOSPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSQUERY:+ fprintf(f, " %s ", flag);++ if (*code >= OP_TYPESTAR)+ {+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP)+ {+ print_prop(f, code + 1, "", " ");+ extra = 2;+ }+ else fprintf(f, "%s", OP_names[code[1]]);+ }+ else extra = print_char(f, code+1, utf);+ fprintf(f, "%s", OP_names[*code]);+ break;++ case OP_EXACTI:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_POSUPTOI:+ flag = "/i";+ /* Fall through */+ case OP_EXACT:+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_POSUPTO:+ fprintf(f, " %s ", flag);+ extra = print_char(f, code + 1 + IMM2_SIZE, utf);+ fprintf(f, "{");+ if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");+ fprintf(f, "%d}", GET2(code,1));+ if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?");+ else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+");+ break;++ case OP_TYPEEXACT:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEPOSUPTO:+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)+ {+ print_prop(f, code + IMM2_SIZE + 1, " ", " ");+ extra = 2;+ }+ else fprintf(f, " %s", OP_names[code[1 + IMM2_SIZE]]);+ fprintf(f, "{");+ if (*code != OP_TYPEEXACT) fprintf(f, "0,");+ fprintf(f, "%d}", GET2(code,1));+ if (*code == OP_TYPEMINUPTO) fprintf(f, "?");+ else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+");+ break;++ case OP_NOTI:+ flag = "/i";+ /* Fall through */+ case OP_NOT:+ fprintf(f, " %s [^", flag);+ extra = print_char(f, code + 1, utf);+ fprintf(f, "]");+ break;++ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPOSSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTPOSPLUSI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTPOSQUERYI:+ flag = "/i";+ /* Fall through */++ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPOSSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTPOSPLUS:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTPOSQUERY:+ fprintf(f, " %s [^", flag);+ extra = print_char(f, code + 1, utf);+ fprintf(f, "]%s", OP_names[*code]);+ break;++ case OP_NOTEXACTI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTPOSUPTOI:+ flag = "/i";+ /* Fall through */++ case OP_NOTEXACT:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTPOSUPTO:+ fprintf(f, " %s [^", flag);+ extra = print_char(f, code + 1 + IMM2_SIZE, utf);+ fprintf(f, "]{");+ if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");+ fprintf(f, "%d}", GET2(code,1));+ if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?");+ else+ if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+");+ break;++ case OP_RECURSE:+ if (print_lengths) fprintf(f, "%3d ", GET(code, 1));+ else fprintf(f, " ");+ fprintf(f, "%s", OP_names[*code]);+ break;++ case OP_REFI:+ flag = "/i";+ /* Fall through */+ case OP_REF:+ fprintf(f, " %s \\%d", flag, GET2(code,1));+ ccode = code + OP_lengths[*code];+ goto CLASS_REF_REPEAT;++ case OP_DNREFI:+ flag = "/i";+ /* Fall through */+ case OP_DNREF:+ {+ PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;+ fprintf(f, " %s \\k<", flag);+ print_custring(f, entry);+ fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));+ }+ ccode = code + OP_lengths[*code];+ goto CLASS_REF_REPEAT;++ case OP_CALLOUT:+ fprintf(f, " %s %d %d %d", OP_names[*code], code[1 + 2*LINK_SIZE],+ GET(code, 1), GET(code, 1 + LINK_SIZE));+ break;++ case OP_CALLOUT_STR:+ c = code[1 + 4*LINK_SIZE];+ fprintf(f, " %s %c", OP_names[*code], c);+ extra = GET(code, 1 + 2*LINK_SIZE);+ print_custring_bylen(f, code + 2 + 4*LINK_SIZE, extra - 3 - 4*LINK_SIZE);+ for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)+ if (c == PRIV(callout_start_delims)[i])+ {+ c = PRIV(callout_end_delims)[i];+ break;+ }+ fprintf(f, "%c %d %d %d", c, GET(code, 1 + 3*LINK_SIZE), GET(code, 1),+ GET(code, 1 + LINK_SIZE));+ break;++ case OP_PROP:+ case OP_NOTPROP:+ print_prop(f, code, " ", "");+ break;++ /* OP_XCLASS cannot occur in 8-bit, non-UTF mode. However, there's no harm+ in having this code always here, and it makes it less messy without all+ those #ifdefs. */++ case OP_CLASS:+ case OP_NCLASS:+ case OP_XCLASS:+ {+ unsigned int min, max;+ BOOL printmap;+ BOOL invertmap = FALSE;+ uint8_t *map;+ uint8_t inverted_map[32];++ fprintf(f, " [");++ if (*code == OP_XCLASS)+ {+ extra = GET(code, 1);+ ccode = code + LINK_SIZE + 1;+ printmap = (*ccode & XCL_MAP) != 0;+ if ((*ccode & XCL_NOT) != 0)+ {+ invertmap = (*ccode & XCL_HASPROP) == 0;+ fprintf(f, "^");+ }+ ccode++;+ }+ else+ {+ printmap = TRUE;+ ccode = code + 1;+ }++ /* Print a bit map */++ if (printmap)+ {+ map = (uint8_t *)ccode;+ if (invertmap)+ {+ /* Using 255 ^ instead of ~ avoids clang sanitize warning. */+ for (i = 0; i < 32; i++) inverted_map[i] = 255 ^ map[i];+ map = inverted_map;+ }++ for (i = 0; i < 256; i++)+ {+ if ((map[i/8] & (1u << (i&7))) != 0)+ {+ int j;+ for (j = i+1; j < 256; j++)+ if ((map[j/8] & (1u << (j&7))) == 0) break;+ if (i == '-' || i == ']') fprintf(f, "\\");+ if (PRINTABLE(i)) fprintf(f, "%c", i);+ else fprintf(f, "\\x%02x", i);+ if (--j > i)+ {+ if (j != i + 1) fprintf(f, "-");+ if (j == '-' || j == ']') fprintf(f, "\\");+ if (PRINTABLE(j)) fprintf(f, "%c", j);+ else fprintf(f, "\\x%02x", j);+ }+ i = j;+ }+ }+ ccode += 32 / sizeof(PCRE2_UCHAR);+ }++ /* For an XCLASS there is always some additional data */++ if (*code == OP_XCLASS)+ {+ PCRE2_UCHAR ch;+ while ((ch = *ccode++) != XCL_END)+ {+ BOOL not = FALSE;+ const char *notch = "";++ switch(ch)+ {+ case XCL_NOTPROP:+ not = TRUE;+ notch = "^";+ /* Fall through */++ case XCL_PROP:+ {+ unsigned int ptype = *ccode++;+ unsigned int pvalue = *ccode++;++ switch(ptype)+ {+ case PT_PXGRAPH:+ fprintf(f, "[:%sgraph:]", notch);+ break;++ case PT_PXPRINT:+ fprintf(f, "[:%sprint:]", notch);+ break;++ case PT_PXPUNCT:+ fprintf(f, "[:%spunct:]", notch);+ break;++ default:+ fprintf(f, "\\%c{%s}", (not? 'P':'p'),+ get_ucpname(ptype, pvalue));+ break;+ }+ }+ break;++ default:+ ccode += 1 + print_char(f, ccode, utf);+ if (ch == XCL_RANGE)+ {+ fprintf(f, "-");+ ccode += 1 + print_char(f, ccode, utf);+ }+ break;+ }+ }+ }++ /* Indicate a non-UTF class which was created by negation */++ fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");++ /* Handle repeats after a class or a back reference */++ CLASS_REF_REPEAT:+ switch(*ccode)+ {+ 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:+ fprintf(f, "%s", OP_names[*ccode]);+ extra += OP_lengths[*ccode];+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ min = GET2(ccode,1);+ max = GET2(ccode,1 + IMM2_SIZE);+ if (max == 0) fprintf(f, "{%u,}", min);+ else fprintf(f, "{%u,%u}", min, max);+ if (*ccode == OP_CRMINRANGE) fprintf(f, "?");+ else if (*ccode == OP_CRPOSRANGE) fprintf(f, "+");+ extra += OP_lengths[*ccode];+ break;++ /* Do nothing if it's not a repeat; this code stops picky compilers+ warning about the lack of a default code path. */++ default:+ break;+ }+ }+ break;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ fprintf(f, " %s ", OP_names[*code]);+ print_custring_bylen(f, code + 2, code[1]);+ extra += code[1];+ break;++ case OP_THEN:+ fprintf(f, " %s", OP_names[*code]);+ break;++ case OP_CIRCM:+ case OP_DOLLM:+ flag = "/m";+ /* Fall through */++ /* Anything else is just an item with no data, but possibly a flag. */++ default:+ fprintf(f, " %s %s", flag, OP_names[*code]);+ break;+ }++ code += OP_lengths[*code] + extra;+ fprintf(f, "\n");+ }+}++/* End of pcre2_printint.c */
+ src/c/pcre2/src/pcre2_script_run.c view
@@ -0,0 +1,441 @@+/*************************************************+* 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) 2016-2018 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.+-----------------------------------------------------------------------------+*/++/* This module contains the function for checking a script run. */++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include "pcre2_internal.h"+++/*************************************************+* Check script run *+*************************************************/++/* A script run is conceptually a sequence of characters all in the same+Unicode script. However, it isn't quite that simple. There are special rules+for scripts that are commonly used together, and also special rules for digits.+This function implements the appropriate checks, which is possible only when+PCRE2 is compiled with Unicode support. The function returns TRUE if there is+no Unicode support; however, it should never be called in that circumstance+because an error is given by pcre2_compile() if a script run is called for in a+version of PCRE2 compiled without Unicode support.++Arguments:+ pgr point to the first character+ endptr point after the last character+ utf TRUE if in UTF mode++Returns: TRUE if this is a valid script run+*/++/* These dummy values must be less than the negation of the largest offset in+the PRIV(ucd_script_sets) vector, which is held in a 16-bit field in UCD+records (and is only likely to be a few hundred). */++#define SCRIPT_UNSET (-99999)+#define SCRIPT_HANPENDING (-99998)+#define SCRIPT_HANHIRAKATA (-99997)+#define SCRIPT_HANBOPOMOFO (-99996)+#define SCRIPT_HANHANGUL (-99995)+#define SCRIPT_LIST (-99994)++#define INTERSECTION_LIST_SIZE 50++BOOL+PRIV(script_run)(PCRE2_SPTR ptr, PCRE2_SPTR endptr, BOOL utf)+{+#ifdef SUPPORT_UNICODE+int require_script = SCRIPT_UNSET;+uint8_t intersection_list[INTERSECTION_LIST_SIZE];+const uint8_t *require_list = NULL;+uint32_t require_digitset = 0;+uint32_t c;++#if PCRE2_CODE_UNIT_WIDTH == 32+(void)utf; /* Avoid compiler warning */+#endif++/* Any string containing fewer than 2 characters is a valid script run. */++if (ptr >= endptr) return TRUE;+GETCHARINCTEST(c, ptr);+if (ptr >= endptr) return TRUE;++/* Scan strings of two or more characters, checking the Unicode characteristics+of each code point. We make use of the Script Extensions property. There is+special code for scripts that can be combined with characters from the Han+Chinese script. This may be used in conjunction with four other scripts in+these combinations:++. Han with Hiragana and Katakana is allowed (for Japanese).+. Han with Bopomofo is allowed (for Taiwanese Mandarin).+. Han with Hangul is allowed (for Korean).++If the first significant character's script is one of the four, the required+script type is immediately known. However, if the first significant+character's script is Han, we have to keep checking for a non-Han character.+Hence the SCRIPT_HANPENDING state. */++for (;;)+ {+ const ucd_record *ucd = GET_UCD(c);+ int32_t scriptx = ucd->scriptx;++ /* If the script extension is Unknown, the string is not a valid script run.+ Such characters can only form script runs of length one. */++ if (scriptx == ucp_Unknown) return FALSE;++ /* A character whose script extension is Inherited is always accepted with+ any script, and plays no further part in this testing. A character whose+ script is Common is always accepted, but must still be tested for a digit+ below. The scriptx value at this point is non-zero, because zero is+ ucp_Unknown, tested for above. */++ if (scriptx != ucp_Inherited)+ {+ if (scriptx != ucp_Common)+ {+ /* If the script extension value is positive, the character is not a mark+ that can be used with many scripts. In the simple case we either set or+ compare with the required script. However, handling the scripts that can+ combine with Han are more complicated, as is the case when the previous+ characters have been man-script marks. */++ if (scriptx > 0)+ {+ switch(require_script)+ {+ /* Either the first significant character (require_script unset) or+ after only Han characters. */++ case SCRIPT_UNSET:+ case SCRIPT_HANPENDING:+ switch(scriptx)+ {+ case ucp_Han:+ require_script = SCRIPT_HANPENDING;+ break;++ case ucp_Hiragana:+ case ucp_Katakana:+ require_script = SCRIPT_HANHIRAKATA;+ break;++ case ucp_Bopomofo:+ require_script = SCRIPT_HANBOPOMOFO;+ break;++ case ucp_Hangul:+ require_script = SCRIPT_HANHANGUL;+ break;++ /* Not a Han-related script. If expecting one, fail. Otherise set+ the requirement to this script. */++ default:+ if (require_script == SCRIPT_HANPENDING) return FALSE;+ require_script = scriptx;+ break;+ }+ break;++ /* Previously encountered one of the "with Han" scripts. Check that+ this character is appropriate. */++ case SCRIPT_HANHIRAKATA:+ if (scriptx != ucp_Han && scriptx != ucp_Hiragana && + scriptx != ucp_Katakana)+ return FALSE;+ break;++ case SCRIPT_HANBOPOMOFO:+ if (scriptx != ucp_Han && scriptx != ucp_Bopomofo) return FALSE;+ break;++ case SCRIPT_HANHANGUL:+ if (scriptx != ucp_Han && scriptx != ucp_Hangul) return FALSE;+ break;++ /* We have a list of scripts to check that is derived from one or+ more previous characters. This is either one of the lists in+ ucd_script_sets[] (for one previous character) or the intersection of+ several lists for multiple characters. */++ case SCRIPT_LIST:+ {+ const uint8_t *list;+ for (list = require_list; *list != 0; list++)+ {+ if (*list == scriptx) break;+ }+ if (*list == 0) return FALSE;+ }++ /* The rest of the string must be in this script, but we have to + allow for the Han complications. */+ + switch(scriptx)+ {+ case ucp_Han:+ require_script = SCRIPT_HANPENDING;+ break;++ case ucp_Hiragana:+ case ucp_Katakana:+ require_script = SCRIPT_HANHIRAKATA;+ break;++ case ucp_Bopomofo:+ require_script = SCRIPT_HANBOPOMOFO;+ break;++ case ucp_Hangul:+ require_script = SCRIPT_HANHANGUL;+ break;++ default:+ require_script = scriptx;+ break;+ } + break;++ /* This is the easy case when a single script is required. */++ default:+ if (scriptx != require_script) return FALSE;+ break;+ }+ } /* End of handing positive scriptx */++ /* If scriptx is negative, this character is a mark-type character that+ has a list of permitted scripts. */++ else+ {+ uint32_t chspecial;+ const uint8_t *clist, *rlist;+ const uint8_t *list = PRIV(ucd_script_sets) - scriptx;+ + switch(require_script)+ {+ case SCRIPT_UNSET:+ require_list = PRIV(ucd_script_sets) - scriptx;+ require_script = SCRIPT_LIST;+ break;++ /* An inspection of the Unicode 11.0.0 files shows that there are the+ following types of Script Extension list that involve the Han,+ Bopomofo, Hiragana, Katakana, and Hangul scripts:++ . Bopomofo + Han+ . Han + Hiragana + Katakana+ . Hiragana + Katakana+ . Bopopmofo + Hangul + Han + Hiragana + Katakana++ The following code tries to make sense of this. */++#define FOUND_BOPOMOFO 1+#define FOUND_HIRAGANA 2+#define FOUND_KATAKANA 4+#define FOUND_HANGUL 8++ case SCRIPT_HANPENDING:+ chspecial = 0;+ for (; *list != 0; list++)+ {+ switch (*list)+ {+ case ucp_Bopomofo: chspecial |= FOUND_BOPOMOFO; break;+ case ucp_Hiragana: chspecial |= FOUND_HIRAGANA; break;+ case ucp_Katakana: chspecial |= FOUND_KATAKANA; break;+ case ucp_Hangul: chspecial |= FOUND_HANGUL; break;+ default: break;+ }+ }++ if (chspecial == 0) return FALSE;++ if (chspecial == FOUND_BOPOMOFO)+ {+ require_script = SCRIPT_HANBOPOMOFO;+ }+ else if (chspecial == (FOUND_HIRAGANA|FOUND_KATAKANA))+ {+ require_script = SCRIPT_HANHIRAKATA;+ }++ /* Otherwise it must be allowed with all of them, so remain in+ the pending state. */++ break;++ case SCRIPT_HANHIRAKATA:+ for (; *list != 0; list++)+ {+ if (*list == ucp_Hiragana || *list == ucp_Katakana) break;+ }+ if (*list == 0) return FALSE;+ break;++ case SCRIPT_HANBOPOMOFO:+ for (; *list != 0; list++)+ {+ if (*list == ucp_Bopomofo) break;+ }+ if (*list == 0) return FALSE;+ break;++ case SCRIPT_HANHANGUL:+ for (; *list != 0; list++)+ {+ if (*list == ucp_Hangul) break;+ }+ if (*list == 0) return FALSE;+ break;++ /* Previously encountered one or more characters that are allowed+ with a list of scripts. Build the intersection of the required list+ with this character's list in intersection_list[]. This code is+ written so that it still works OK if the required list is already in+ that vector. */++ case SCRIPT_LIST:+ {+ int i = 0;+ for (rlist = require_list; *rlist != 0; rlist++)+ {+ for (clist = list; *clist != 0; clist++)+ {+ if (*rlist == *clist)+ {+ intersection_list[i++] = *rlist;+ break;+ }+ }+ }+ if (i == 0) return FALSE; /* No scripts in common */++ /* If there's just one script in common, we can set it as the+ unique required script. Otherwise, terminate the intersection list+ and make it the required list. */++ if (i == 1)+ {+ require_script = intersection_list[0];+ }+ else+ {+ intersection_list[i] = 0;+ require_list = intersection_list;+ }+ }+ break;++ /* The previously set required script is a single script, not+ Han-related. Check that it is in this character's list. */++ default:+ for (; *list != 0; list++)+ {+ if (*list == require_script) break;+ }+ if (*list == 0) return FALSE;+ break;+ }+ } /* End of handling negative scriptx */+ } /* End of checking non-Common character */++ /* The character is in an acceptable script. We must now ensure that all+ decimal digits in the string come from the same set. Some scripts (e.g.+ Common, Arabic) have more than one set of decimal digits. This code does+ not allow mixing sets, even within the same script. The vector called+ PRIV(ucd_digit_sets)[] contains, in its first element, the number of+ following elements, and then, in ascending order, the code points of the+ '9' characters in every set of 10 digits. Each set is identified by the+ offset in the vector of its '9' character. An initial check of the first+ value picks up ASCII digits quickly. Otherwise, a binary chop is used. */++ if (ucd->chartype == ucp_Nd)+ {+ uint32_t digitset;++ if (c <= PRIV(ucd_digit_sets)[1]) digitset = 1; else+ {+ int mid;+ int bot = 1;+ int top = PRIV(ucd_digit_sets)[0];+ for (;;)+ {+ if (top <= bot + 1) /* <= rather than == is paranoia */+ {+ digitset = top;+ break;+ }+ mid = (top + bot) / 2;+ if (c <= PRIV(ucd_digit_sets)[mid]) top = mid; else bot = mid;+ }+ }++ /* A required value of 0 means "unset". */++ if (require_digitset == 0) require_digitset = digitset;+ else if (digitset != require_digitset) return FALSE;+ } /* End digit handling */+ } /* End checking non-Inherited character */++ /* If we haven't yet got to the end, pick up the next character. */++ if (ptr >= endptr) return TRUE;+ GETCHARINCTEST(c, ptr);+ } /* End checking loop */++#else /* NOT SUPPORT_UNICODE */+(void)ptr;+(void)endptr;+(void)utf;+return TRUE;+#endif /* SUPPORT_UNICODE */+}++/* End of pcre2_script_run.c */
+ src/c/pcre2/src/pcre2_serialize.c view
@@ -0,0 +1,286 @@+/*************************************************+* 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) 2016-2020 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.+-----------------------------------------------------------------------------+*/++/* This module contains functions for serializing and deserializing+a sequence of compiled codes. */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif+++#include "pcre2_internal.h"++/* Magic number to provide a small check against being handed junk. */++#define SERIALIZED_DATA_MAGIC 0x50523253u++/* Deserialization is limited to the current PCRE version and+character width. */++#define SERIALIZED_DATA_VERSION \+ ((PCRE2_MAJOR) | ((PCRE2_MINOR) << 16))++#define SERIALIZED_DATA_CONFIG \+ (sizeof(PCRE2_UCHAR) | ((sizeof(void*)) << 8) | ((sizeof(PCRE2_SIZE)) << 16))++++/*************************************************+* Serialize compiled patterns *+*************************************************/++PCRE2_EXP_DEFN int32_t PCRE2_CALL_CONVENTION+pcre2_serialize_encode(const pcre2_code **codes, int32_t number_of_codes,+ uint8_t **serialized_bytes, PCRE2_SIZE *serialized_size,+ pcre2_general_context *gcontext)+{+uint8_t *bytes;+uint8_t *dst_bytes;+int32_t i;+PCRE2_SIZE total_size;+const pcre2_real_code *re;+const uint8_t *tables;+pcre2_serialized_data *data;++const pcre2_memctl *memctl = (gcontext != NULL) ?+ &gcontext->memctl : &PRIV(default_compile_context).memctl;++if (codes == NULL || serialized_bytes == NULL || serialized_size == NULL)+ return PCRE2_ERROR_NULL;++if (number_of_codes <= 0) return PCRE2_ERROR_BADDATA;++/* Compute total size. */+total_size = sizeof(pcre2_serialized_data) + TABLES_LENGTH;+tables = NULL;++for (i = 0; i < number_of_codes; i++)+ {+ if (codes[i] == NULL) return PCRE2_ERROR_NULL;+ re = (const pcre2_real_code *)(codes[i]);+ if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;+ if (tables == NULL)+ tables = re->tables;+ else if (tables != re->tables)+ return PCRE2_ERROR_MIXEDTABLES;+ total_size += re->blocksize;+ }++/* Initialize the byte stream. */+bytes = memctl->malloc(total_size + sizeof(pcre2_memctl), memctl->memory_data);+if (bytes == NULL) return PCRE2_ERROR_NOMEMORY;++/* The controller is stored as a hidden parameter. */+memcpy(bytes, memctl, sizeof(pcre2_memctl));+bytes += sizeof(pcre2_memctl);++data = (pcre2_serialized_data *)bytes;+data->magic = SERIALIZED_DATA_MAGIC;+data->version = SERIALIZED_DATA_VERSION;+data->config = SERIALIZED_DATA_CONFIG;+data->number_of_codes = number_of_codes;++/* Copy all compiled code data. */+dst_bytes = bytes + sizeof(pcre2_serialized_data);+memcpy(dst_bytes, tables, TABLES_LENGTH);+dst_bytes += TABLES_LENGTH;++for (i = 0; i < number_of_codes; i++)+ {+ re = (const pcre2_real_code *)(codes[i]);+ (void)memcpy(dst_bytes, (char *)re, re->blocksize);+ + /* Certain fields in the compiled code block are re-set during + deserialization. In order to ensure that the serialized data stream is always + the same for the same pattern, set them to zero here. We can't assume the + copy of the pattern is correctly aligned for accessing the fields as part of + a structure. Note the use of sizeof(void *) in the second of these, to+ specify the size of a pointer. If sizeof(uint8_t *) is used (tables is a + pointer to uint8_t), gcc gives a warning because the first argument is also a + pointer to uint8_t. Casting the first argument to (void *) can stop this, but + it didn't stop Coverity giving the same complaint. */+ + (void)memset(dst_bytes + offsetof(pcre2_real_code, memctl), 0, + sizeof(pcre2_memctl));+ (void)memset(dst_bytes + offsetof(pcre2_real_code, tables), 0, + sizeof(void *));+ (void)memset(dst_bytes + offsetof(pcre2_real_code, executable_jit), 0,+ sizeof(void *)); + + dst_bytes += re->blocksize;+ }++*serialized_bytes = bytes;+*serialized_size = total_size;+return number_of_codes;+}+++/*************************************************+* Deserialize compiled patterns *+*************************************************/++PCRE2_EXP_DEFN int32_t PCRE2_CALL_CONVENTION+pcre2_serialize_decode(pcre2_code **codes, int32_t number_of_codes,+ const uint8_t *bytes, pcre2_general_context *gcontext)+{+const pcre2_serialized_data *data = (const pcre2_serialized_data *)bytes;+const pcre2_memctl *memctl = (gcontext != NULL) ?+ &gcontext->memctl : &PRIV(default_compile_context).memctl;++const uint8_t *src_bytes;+pcre2_real_code *dst_re;+uint8_t *tables;+int32_t i, j;++/* Sanity checks. */++if (data == NULL || codes == NULL) return PCRE2_ERROR_NULL;+if (number_of_codes <= 0) return PCRE2_ERROR_BADDATA;+if (data->number_of_codes <= 0) return PCRE2_ERROR_BADSERIALIZEDDATA;+if (data->magic != SERIALIZED_DATA_MAGIC) return PCRE2_ERROR_BADMAGIC;+if (data->version != SERIALIZED_DATA_VERSION) return PCRE2_ERROR_BADMODE;+if (data->config != SERIALIZED_DATA_CONFIG) return PCRE2_ERROR_BADMODE;++if (number_of_codes > data->number_of_codes)+ number_of_codes = data->number_of_codes;++src_bytes = bytes + sizeof(pcre2_serialized_data);++/* Decode tables. The reference count for the tables is stored immediately+following them. */++tables = memctl->malloc(TABLES_LENGTH + sizeof(PCRE2_SIZE), memctl->memory_data);+if (tables == NULL) return PCRE2_ERROR_NOMEMORY;++memcpy(tables, src_bytes, TABLES_LENGTH);+*(PCRE2_SIZE *)(tables + TABLES_LENGTH) = number_of_codes;+src_bytes += TABLES_LENGTH;++/* Decode the byte stream. We must not try to read the size from the compiled+code block in the stream, because it might be unaligned, which causes errors on+hardware such as Sparc-64 that doesn't like unaligned memory accesses. The type+of the blocksize field is given its own name to ensure that it is the same here+as in the block. */++for (i = 0; i < number_of_codes; i++)+ {+ CODE_BLOCKSIZE_TYPE blocksize;+ memcpy(&blocksize, src_bytes + offsetof(pcre2_real_code, blocksize),+ sizeof(CODE_BLOCKSIZE_TYPE));+ if (blocksize <= sizeof(pcre2_real_code))+ return PCRE2_ERROR_BADSERIALIZEDDATA;++ /* The allocator provided by gcontext replaces the original one. */++ dst_re = (pcre2_real_code *)PRIV(memctl_malloc)(blocksize,+ (pcre2_memctl *)gcontext);+ if (dst_re == NULL)+ {+ memctl->free(tables, memctl->memory_data);+ for (j = 0; j < i; j++)+ {+ memctl->free(codes[j], memctl->memory_data);+ codes[j] = NULL;+ }+ return PCRE2_ERROR_NOMEMORY;+ }++ /* The new allocator must be preserved. */++ memcpy(((uint8_t *)dst_re) + sizeof(pcre2_memctl),+ src_bytes + sizeof(pcre2_memctl), blocksize - sizeof(pcre2_memctl));+ if (dst_re->magic_number != MAGIC_NUMBER ||+ dst_re->name_entry_size > MAX_NAME_SIZE + IMM2_SIZE + 1 ||+ dst_re->name_count > MAX_NAME_COUNT)+ { + memctl->free(dst_re, memctl->memory_data); + return PCRE2_ERROR_BADSERIALIZEDDATA;+ } ++ /* At the moment only one table is supported. */++ dst_re->tables = tables;+ dst_re->executable_jit = NULL;+ dst_re->flags |= PCRE2_DEREF_TABLES;++ codes[i] = dst_re;+ src_bytes += blocksize;+ }++return number_of_codes;+}+++/*************************************************+* Get the number of serialized patterns *+*************************************************/++PCRE2_EXP_DEFN int32_t PCRE2_CALL_CONVENTION+pcre2_serialize_get_number_of_codes(const uint8_t *bytes)+{+const pcre2_serialized_data *data = (const pcre2_serialized_data *)bytes;++if (data == NULL) return PCRE2_ERROR_NULL;+if (data->magic != SERIALIZED_DATA_MAGIC) return PCRE2_ERROR_BADMAGIC;+if (data->version != SERIALIZED_DATA_VERSION) return PCRE2_ERROR_BADMODE;+if (data->config != SERIALIZED_DATA_CONFIG) return PCRE2_ERROR_BADMODE;++return data->number_of_codes;+}+++/*************************************************+* Free the allocated stream *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_serialize_free(uint8_t *bytes)+{+if (bytes != NULL)+ {+ pcre2_memctl *memctl = (pcre2_memctl *)(bytes - sizeof(pcre2_memctl));+ memctl->free(memctl, memctl->memory_data);+ }+}++/* End of pcre2_serialize.c */
+ src/c/pcre2/src/pcre2_string_utils.c view
@@ -0,0 +1,237 @@+/*************************************************+* 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) 2018 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.+-----------------------------------------------------------------------------+*/++/* This module contains internal functions for comparing and finding the length+of strings. These are used instead of strcmp() etc because the standard+functions work only on 8-bit data. */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include "pcre2_internal.h"+++/*************************************************+* Emulated memmove() for systems without it *+*************************************************/++/* This function can make use of bcopy() if it is available. Otherwise do it by+steam, as there some non-Unix environments that lack both memmove() and+bcopy(). */++#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)+void *+PRIV(memmove)(void *d, const void *s, size_t n)+{+#ifdef HAVE_BCOPY+bcopy(s, d, n);+return d;+#else+size_t i;+unsigned char *dest = (unsigned char *)d;+const unsigned char *src = (const unsigned char *)s;+if (dest > src)+ {+ dest += n;+ src += n;+ for (i = 0; i < n; ++i) *(--dest) = *(--src);+ return (void *)dest;+ }+else+ {+ for (i = 0; i < n; ++i) *dest++ = *src++;+ return (void *)(dest - n);+ }+#endif /* not HAVE_BCOPY */+}+#endif /* not VPCOMPAT && not HAVE_MEMMOVE */+++/*************************************************+* Compare two zero-terminated PCRE2 strings *+*************************************************/++/*+Arguments:+ str1 first string+ str2 second string++Returns: 0, 1, or -1+*/++int+PRIV(strcmp)(PCRE2_SPTR str1, PCRE2_SPTR str2)+{+PCRE2_UCHAR c1, c2;+while (*str1 != '\0' || *str2 != '\0')+ {+ c1 = *str1++;+ c2 = *str2++;+ if (c1 != c2) return ((c1 > c2) << 1) - 1;+ }+return 0;+}+++/*************************************************+* Compare zero-terminated PCRE2 & 8-bit strings *+*************************************************/++/* As the 8-bit string is almost always a literal, its type is specified as+const char *.++Arguments:+ str1 first string+ str2 second string++Returns: 0, 1, or -1+*/++int+PRIV(strcmp_c8)(PCRE2_SPTR str1, const char *str2)+{+PCRE2_UCHAR c1, c2;+while (*str1 != '\0' || *str2 != '\0')+ {+ c1 = *str1++;+ c2 = *str2++;+ if (c1 != c2) return ((c1 > c2) << 1) - 1;+ }+return 0;+}+++/*************************************************+* Compare two PCRE2 strings, given a length *+*************************************************/++/*+Arguments:+ str1 first string+ str2 second string+ len the length++Returns: 0, 1, or -1+*/++int+PRIV(strncmp)(PCRE2_SPTR str1, PCRE2_SPTR str2, size_t len)+{+PCRE2_UCHAR c1, c2;+for (; len > 0; len--)+ {+ c1 = *str1++;+ c2 = *str2++;+ if (c1 != c2) return ((c1 > c2) << 1) - 1;+ }+return 0;+}+++/*************************************************+* Compare PCRE2 string to 8-bit string by length *+*************************************************/++/* As the 8-bit string is almost always a literal, its type is specified as+const char *.++Arguments:+ str1 first string+ str2 second string+ len the length++Returns: 0, 1, or -1+*/++int+PRIV(strncmp_c8)(PCRE2_SPTR str1, const char *str2, size_t len)+{+PCRE2_UCHAR c1, c2;+for (; len > 0; len--)+ {+ c1 = *str1++;+ c2 = *str2++;+ if (c1 != c2) return ((c1 > c2) << 1) - 1;+ }+return 0;+}+++/*************************************************+* Find the length of a PCRE2 string *+*************************************************/++/*+Argument: the string+Returns: the length+*/++PCRE2_SIZE+PRIV(strlen)(PCRE2_SPTR str)+{+PCRE2_SIZE c = 0;+while (*str++ != 0) c++;+return c;+}+++/*************************************************+* Copy 8-bit 0-terminated string to PCRE2 string *+*************************************************/++/* Arguments:+ str1 buffer to receive the string+ str2 8-bit string to be copied++Returns: the number of code units used (excluding trailing zero)+*/++PCRE2_SIZE+PRIV(strcpy_c8)(PCRE2_UCHAR *str1, const char *str2)+{+PCRE2_UCHAR *t = str1;+while (*str2 != 0) *t++ = *str2++;+*t = 0;+return t - str1;+}++/* End of pcre2_string_utils.c */
+ src/c/pcre2/src/pcre2_study.c view
@@ -0,0 +1,1825 @@+/*************************************************+* 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) 2016-2020 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.+-----------------------------------------------------------------------------+*/++/* This module contains functions for scanning a compiled pattern and+collecting data (e.g. minimum matching length). */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include "pcre2_internal.h"++/* The maximum remembered capturing brackets minimum. */++#define MAX_CACHE_BACKREF 128++/* Set a bit in the starting code unit bit map. */++#define SET_BIT(c) re->start_bitmap[(c)/8] |= (1u << ((c)&7))++/* Returns from set_start_bits() */++enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE, SSB_UNKNOWN, SSB_TOODEEP };+++/*************************************************+* Find the minimum subject length for a group *+*************************************************/++/* Scan a parenthesized group and compute the minimum length of subject that+is needed to match it. This is a lower bound; it does not mean there is a+string of that length that matches. In UTF mode, the result is in characters+rather than code units. The field in a compiled pattern for storing the minimum+length is 16-bits long (on the grounds that anything longer than that is+pathological), so we give up when we reach that amount. This also means that+integer overflow for really crazy patterns cannot happen.++Backreference minimum lengths are cached to speed up multiple references. This+function is called only when the highest back reference in the pattern is less+than or equal to MAX_CACHE_BACKREF, which is one less than the size of the+caching vector. The zeroth element contains the number of the highest set+value.++Arguments:+ re compiled pattern block+ code pointer to start of group (the bracket)+ startcode pointer to start of the whole pattern's code+ utf UTF flag+ recurses chain of recurse_check to catch mutual recursion+ countptr pointer to call count (to catch over complexity)+ backref_cache vector for caching back references.++This function is no longer called when the pattern contains (*ACCEPT); however,+the old code for returning -1 is retained, just in case.++Returns: the minimum length+ -1 \C in UTF-8 mode+ or (*ACCEPT)+ or pattern too complicated+ -2 internal error (missing capturing bracket)+ -3 internal error (opcode not listed)+*/++static int+find_minlength(const pcre2_real_code *re, PCRE2_SPTR code,+ PCRE2_SPTR startcode, BOOL utf, recurse_check *recurses, int *countptr,+ int *backref_cache)+{+int length = -1;+int branchlength = 0;+int prev_cap_recno = -1;+int prev_cap_d = 0;+int prev_recurse_recno = -1;+int prev_recurse_d = 0;+uint32_t once_fudge = 0;+BOOL had_recurse = FALSE;+BOOL dupcapused = (re->flags & PCRE2_DUPCAPUSED) != 0;+PCRE2_SPTR nextbranch = code + GET(code, 1);+PCRE2_UCHAR *cc = (PCRE2_UCHAR *)code + 1 + LINK_SIZE;+recurse_check this_recurse;++/* If this is a "could be empty" group, its minimum length is 0. */++if (*code >= OP_SBRA && *code <= OP_SCOND) return 0;++/* Skip over capturing bracket number */++if (*code == OP_CBRA || *code == OP_CBRAPOS) cc += IMM2_SIZE;++/* A large and/or complex regex can take too long to process. */++if ((*countptr)++ > 1000) return -1;++/* Scan along the opcodes for this branch. If we get to the end of the branch,+check the length against that of the other branches. If the accumulated length+passes 16-bits, reset to that value and skip the rest of the branch. */++for (;;)+ {+ int d, min, recno;+ PCRE2_UCHAR op, *cs, *ce;++ if (branchlength >= UINT16_MAX)+ {+ branchlength = UINT16_MAX;+ cc = (PCRE2_UCHAR *)nextbranch;+ }++ op = *cc;+ switch (op)+ {+ case OP_COND:+ case OP_SCOND:++ /* If there is only one branch in a condition, the implied branch has zero+ length, so we don't add anything. This covers the DEFINE "condition"+ automatically. If there are two branches we can treat it the same as any+ other non-capturing subpattern. */++ cs = cc + GET(cc, 1);+ if (*cs != OP_ALT)+ {+ cc = cs + 1 + LINK_SIZE;+ break;+ }+ goto PROCESS_NON_CAPTURE;++ case OP_BRA:+ /* There's a special case of OP_BRA, when it is wrapped round a repeated+ OP_RECURSE. We'd like to process the latter at this level so that+ remembering the value works for repeated cases. So we do nothing, but+ set a fudge value to skip over the OP_KET after the recurse. */++ if (cc[1+LINK_SIZE] == OP_RECURSE && cc[2*(1+LINK_SIZE)] == OP_KET)+ {+ once_fudge = 1 + LINK_SIZE;+ cc += 1 + LINK_SIZE;+ break;+ }+ /* Fall through */++ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_SBRA:+ case OP_BRAPOS:+ case OP_SBRAPOS:+ PROCESS_NON_CAPTURE:+ d = find_minlength(re, cc, startcode, utf, recurses, countptr,+ backref_cache);+ if (d < 0) return d;+ branchlength += d;+ do cc += GET(cc, 1); while (*cc == OP_ALT);+ cc += 1 + LINK_SIZE;+ break;++ /* To save time for repeated capturing subpatterns, we remember the+ length of the previous one. Unfortunately we can't do the same for+ the unnumbered ones above. Nor can we do this if (?| is present in the+ pattern because captures with the same number are not then identical. */++ case OP_CBRA:+ case OP_SCBRA:+ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ recno = (int)GET2(cc, 1+LINK_SIZE);+ if (dupcapused || recno != prev_cap_recno)+ {+ prev_cap_recno = recno;+ prev_cap_d = find_minlength(re, cc, startcode, utf, recurses, countptr,+ backref_cache);+ if (prev_cap_d < 0) return prev_cap_d;+ }+ branchlength += prev_cap_d;+ do cc += GET(cc, 1); while (*cc == OP_ALT);+ cc += 1 + LINK_SIZE;+ break;++ /* ACCEPT makes things far too complicated; we have to give up. In fact,+ from 10.34 onwards, if a pattern contains (*ACCEPT), this function is not+ used. However, leave the code in place, just in case. */++ case OP_ACCEPT:+ case OP_ASSERT_ACCEPT:+ return -1;++ /* Reached end of a branch; if it's a ket it is the end of a nested+ call. If it's ALT it is an alternation in a nested call. If it is END it's+ the end of the outer call. All can be handled by the same code. If the+ length of any branch is zero, there is no need to scan any subsequent+ branches. */++ case OP_ALT:+ case OP_KET:+ case OP_KETRMAX:+ case OP_KETRMIN:+ case OP_KETRPOS:+ case OP_END:+ if (length < 0 || (!had_recurse && branchlength < length))+ length = branchlength;+ if (op != OP_ALT || length == 0) return length;+ nextbranch = cc + GET(cc, 1);+ cc += 1 + LINK_SIZE;+ branchlength = 0;+ had_recurse = FALSE;+ break;++ /* Skip over assertive subpatterns */++ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ do cc += GET(cc, 1); while (*cc == OP_ALT);+ /* Fall through */++ /* Skip over things that don't match chars */++ case OP_REVERSE:+ case OP_CREF:+ case OP_DNCREF:+ case OP_RREF:+ case OP_DNRREF:+ case OP_FALSE:+ case OP_TRUE:+ case OP_CALLOUT:+ case OP_SOD:+ case OP_SOM:+ case OP_EOD:+ case OP_EODN:+ case OP_CIRC:+ case OP_CIRCM:+ case OP_DOLL:+ case OP_DOLLM:+ case OP_NOT_WORD_BOUNDARY:+ case OP_WORD_BOUNDARY:+ cc += PRIV(OP_lengths)[*cc];+ break;++ case OP_CALLOUT_STR:+ cc += GET(cc, 1 + 2*LINK_SIZE);+ break;++ /* Skip over a subpattern that has a {0} or {0,x} quantifier */++ case OP_BRAZERO:+ case OP_BRAMINZERO:+ case OP_BRAPOSZERO:+ case OP_SKIPZERO:+ cc += PRIV(OP_lengths)[*cc];+ do cc += GET(cc, 1); while (*cc == OP_ALT);+ cc += 1 + LINK_SIZE;+ break;++ /* Handle literal characters and + repetitions */++ case OP_CHAR:+ case OP_CHARI:+ case OP_NOT:+ case OP_NOTI:+ case OP_PLUS:+ case OP_PLUSI:+ case OP_MINPLUS:+ case OP_MINPLUSI:+ case OP_POSPLUS:+ case OP_POSPLUSI:+ case OP_NOTPLUS:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUS:+ case OP_NOTMINPLUSI:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSPLUSI:+ branchlength++;+ cc += 2;+#ifdef SUPPORT_UNICODE+ if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEPOSPLUS:+ branchlength++;+ cc += (cc[1] == OP_PROP || cc[1] == OP_NOTPROP)? 4 : 2;+ break;++ /* Handle exact repetitions. The count is already in characters, but we+ may need to skip over a multibyte character in UTF mode. */++ case OP_EXACT:+ case OP_EXACTI:+ case OP_NOTEXACT:+ case OP_NOTEXACTI:+ branchlength += GET2(cc,1);+ cc += 2 + IMM2_SIZE;+#ifdef SUPPORT_UNICODE+ if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ case OP_TYPEEXACT:+ branchlength += GET2(cc,1);+ cc += 2 + IMM2_SIZE + ((cc[1 + IMM2_SIZE] == OP_PROP+ || cc[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0);+ break;++ /* Handle single-char non-literal matchers */++ case OP_PROP:+ case OP_NOTPROP:+ cc += 2;+ /* Fall through */++ case OP_NOT_DIGIT:+ case OP_DIGIT:+ case OP_NOT_WHITESPACE:+ case OP_WHITESPACE:+ case OP_NOT_WORDCHAR:+ case OP_WORDCHAR:+ case OP_ANY:+ case OP_ALLANY:+ case OP_EXTUNI:+ case OP_HSPACE:+ case OP_NOT_HSPACE:+ case OP_VSPACE:+ case OP_NOT_VSPACE:+ branchlength++;+ cc++;+ break;++ /* "Any newline" might match two characters, but it also might match just+ one. */++ case OP_ANYNL:+ branchlength += 1;+ cc++;+ break;++ /* The single-byte matcher means we can't proceed in UTF mode. (In+ non-UTF mode \C will actually be turned into OP_ALLANY, so won't ever+ appear, but leave the code, just in case.) */++ case OP_ANYBYTE:+#ifdef SUPPORT_UNICODE+ if (utf) return -1;+#endif+ branchlength++;+ cc++;+ break;++ /* For repeated character types, we have to test for \p and \P, which have+ an extra two bytes of parameters. */++ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSQUERY:+ if (cc[1] == OP_PROP || cc[1] == OP_NOTPROP) cc += 2;+ cc += PRIV(OP_lengths)[op];+ break;++ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEPOSUPTO:+ if (cc[1 + IMM2_SIZE] == OP_PROP+ || cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2;+ cc += PRIV(OP_lengths)[op];+ break;++ /* Check a class for variable quantification */++ case OP_CLASS:+ case OP_NCLASS:+#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+ /* The original code caused an unsigned overflow in 64 bit systems,+ so now we use a conditional statement. */+ if (op == OP_XCLASS)+ cc += GET(cc, 1);+ else+ cc += PRIV(OP_lengths)[OP_CLASS];+#else+ cc += PRIV(OP_lengths)[OP_CLASS];+#endif++ switch (*cc)+ {+ case OP_CRPLUS:+ case OP_CRMINPLUS:+ case OP_CRPOSPLUS:+ branchlength++;+ /* Fall through */++ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSSTAR:+ case OP_CRPOSQUERY:+ cc++;+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ branchlength += GET2(cc,1);+ cc += 1 + 2 * IMM2_SIZE;+ break;++ default:+ branchlength++;+ break;+ }+ break;++ /* Backreferences and subroutine calls (OP_RECURSE) are treated in the same+ way: we find the minimum length for the subpattern. A recursion+ (backreference or subroutine) causes an a flag to be set that causes the+ length of this branch to be ignored. The logic is that a recursion can only+ make sense if there is another alternative that stops the recursing. That+ will provide the minimum length (when no recursion happens).++ If PCRE2_MATCH_UNSET_BACKREF is set, a backreference to an unset bracket+ matches an empty string (by default it causes a matching failure), so in+ that case we must set the minimum length to zero.++ For backreferenes, if duplicate numbers are present in the pattern we check+ for a reference to a duplicate. If it is, we don't know which version will+ be referenced, so we have to set the minimum length to zero. */++ /* Duplicate named pattern back reference. */++ case OP_DNREF:+ case OP_DNREFI:+ if (!dupcapused && (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)+ {+ int count = GET2(cc, 1+IMM2_SIZE);+ PCRE2_UCHAR *slot =+ (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) ++ GET2(cc, 1) * re->name_entry_size;++ d = INT_MAX;++ /* Scan all groups with the same name; find the shortest. */++ while (count-- > 0)+ {+ int dd, i;+ recno = GET2(slot, 0);++ if (recno <= backref_cache[0] && backref_cache[recno] >= 0)+ dd = backref_cache[recno];+ else+ {+ ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno);+ if (cs == NULL) return -2;+ do ce += GET(ce, 1); while (*ce == OP_ALT);++ dd = 0;+ if (!dupcapused ||+ (PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)+ {+ if (cc > cs && cc < ce) /* Simple recursion */+ {+ had_recurse = TRUE;+ }+ else+ {+ recurse_check *r = recurses;+ for (r = recurses; r != NULL; r = r->prev)+ if (r->group == cs) break;+ if (r != NULL) /* Mutual recursion */+ {+ had_recurse = TRUE;+ }+ else+ {+ this_recurse.prev = recurses; /* No recursion */+ this_recurse.group = cs;+ dd = find_minlength(re, cs, startcode, utf, &this_recurse,+ countptr, backref_cache);+ if (dd < 0) return dd;+ }+ }+ }++ backref_cache[recno] = dd;+ for (i = backref_cache[0] + 1; i < recno; i++) backref_cache[i] = -1;+ backref_cache[0] = recno;+ }++ if (dd < d) d = dd;+ if (d <= 0) break; /* No point looking at any more */+ slot += re->name_entry_size;+ }+ }+ else d = 0;+ cc += 1 + 2*IMM2_SIZE;+ goto REPEAT_BACK_REFERENCE;++ /* Single back reference by number. References by name are converted to by+ number when there is no duplication. */++ case OP_REF:+ case OP_REFI:+ recno = GET2(cc, 1);+ if (recno <= backref_cache[0] && backref_cache[recno] >= 0)+ d = backref_cache[recno];+ else+ {+ int i;+ d = 0;++ if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)+ {+ ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno);+ if (cs == NULL) return -2;+ do ce += GET(ce, 1); while (*ce == OP_ALT);++ if (!dupcapused ||+ (PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)+ {+ if (cc > cs && cc < ce) /* Simple recursion */+ {+ had_recurse = TRUE;+ }+ else+ {+ recurse_check *r = recurses;+ for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;+ if (r != NULL) /* Mutual recursion */+ {+ had_recurse = TRUE;+ }+ else /* No recursion */+ {+ this_recurse.prev = recurses;+ this_recurse.group = cs;+ d = find_minlength(re, cs, startcode, utf, &this_recurse, countptr,+ backref_cache);+ if (d < 0) return d;+ }+ }+ }+ }++ backref_cache[recno] = d;+ for (i = backref_cache[0] + 1; i < recno; i++) backref_cache[i] = -1;+ backref_cache[0] = recno;+ }++ cc += 1 + IMM2_SIZE;++ /* Handle repeated back references */++ REPEAT_BACK_REFERENCE:+ switch (*cc)+ {+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSSTAR:+ case OP_CRPOSQUERY:+ min = 0;+ cc++;+ break;++ case OP_CRPLUS:+ case OP_CRMINPLUS:+ case OP_CRPOSPLUS:+ min = 1;+ cc++;+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ min = GET2(cc, 1);+ cc += 1 + 2 * IMM2_SIZE;+ break;++ default:+ min = 1;+ break;+ }++ /* Take care not to overflow: (1) min and d are ints, so check that their+ product is not greater than INT_MAX. (2) branchlength is limited to+ UINT16_MAX (checked at the top of the loop). */++ if ((d > 0 && (INT_MAX/d) < min) || UINT16_MAX - branchlength < min*d)+ branchlength = UINT16_MAX;+ else branchlength += min * d;+ break;++ /* Recursion always refers to the first occurrence of a subpattern with a+ given number. Therefore, we can always make use of caching, even when the+ pattern contains multiple subpatterns with the same number. */++ case OP_RECURSE:+ cs = ce = (PCRE2_UCHAR *)startcode + GET(cc, 1);+ recno = GET2(cs, 1+LINK_SIZE);+ if (recno == prev_recurse_recno)+ {+ branchlength += prev_recurse_d;+ }+ else+ {+ do ce += GET(ce, 1); while (*ce == OP_ALT);+ if (cc > cs && cc < ce) /* Simple recursion */+ had_recurse = TRUE;+ else+ {+ recurse_check *r = recurses;+ for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;+ if (r != NULL) /* Mutual recursion */+ had_recurse = TRUE;+ else+ {+ this_recurse.prev = recurses;+ this_recurse.group = cs;+ prev_recurse_d = find_minlength(re, cs, startcode, utf, &this_recurse,+ countptr, backref_cache);+ if (prev_recurse_d < 0) return prev_recurse_d;+ prev_recurse_recno = recno;+ branchlength += prev_recurse_d;+ }+ }+ }+ cc += 1 + LINK_SIZE + once_fudge;+ once_fudge = 0;+ break;++ /* Anything else does not or need not match a character. We can get the+ item's length from the table, but for those that can match zero occurrences+ of a character, we must take special action for UTF-8 characters. As it+ happens, the "NOT" versions of these opcodes are used at present only for+ ASCII characters, so they could be omitted from this list. However, in+ future that may change, so we include them here so as not to leave a+ gotcha for a future maintainer. */++ case OP_UPTO:+ case OP_UPTOI:+ case OP_NOTUPTO:+ case OP_NOTUPTOI:+ case OP_MINUPTO:+ case OP_MINUPTOI:+ case OP_NOTMINUPTO:+ case OP_NOTMINUPTOI:+ case OP_POSUPTO:+ case OP_POSUPTOI:+ case OP_NOTPOSUPTO:+ case OP_NOTPOSUPTOI:++ case OP_STAR:+ case OP_STARI:+ case OP_NOTSTAR:+ case OP_NOTSTARI:+ case OP_MINSTAR:+ case OP_MINSTARI:+ case OP_NOTMINSTAR:+ case OP_NOTMINSTARI:+ case OP_POSSTAR:+ case OP_POSSTARI:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSSTARI:++ case OP_QUERY:+ case OP_QUERYI:+ case OP_NOTQUERY:+ case OP_NOTQUERYI:+ case OP_MINQUERY:+ case OP_MINQUERYI:+ case OP_NOTMINQUERY:+ case OP_NOTMINQUERYI:+ case OP_POSQUERY:+ case OP_POSQUERYI:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSQUERYI:++ cc += PRIV(OP_lengths)[op];+#ifdef SUPPORT_UNICODE+ if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);+#endif+ break;++ /* Skip these, but we need to add in the name length. */++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ cc += PRIV(OP_lengths)[op] + cc[1];+ break;++ /* The remaining opcodes are just skipped over. */++ case OP_CLOSE:+ case OP_COMMIT:+ case OP_FAIL:+ case OP_PRUNE:+ case OP_SET_SOM:+ case OP_SKIP:+ case OP_THEN:+ cc += PRIV(OP_lengths)[op];+ break;++ /* This should not occur: we list all opcodes explicitly so that when+ new ones get added they are properly considered. */++ default:+ return -3;+ }+ }+/* Control never gets here */+}++++/*************************************************+* Set a bit and maybe its alternate case *+*************************************************/++/* Given a character, set its first code unit's bit in the table, and also the+corresponding bit for the other version of a letter if we are caseless.++Arguments:+ re points to the regex block+ p points to the first code unit of the character+ caseless TRUE if caseless+ utf TRUE for UTF mode+ ucp TRUE for UCP mode++Returns: pointer after the character+*/++static PCRE2_SPTR+set_table_bit(pcre2_real_code *re, PCRE2_SPTR p, BOOL caseless, BOOL utf,+ BOOL ucp)+{+uint32_t c = *p++; /* First code unit */++(void)utf; /* Stop compiler warnings when UTF not supported */+(void)ucp;++/* In 16-bit and 32-bit modes, code units greater than 0xff set the bit for+0xff. */++#if PCRE2_CODE_UNIT_WIDTH != 8+if (c > 0xff) SET_BIT(0xff); else+#endif++SET_BIT(c);++/* In UTF-8 or UTF-16 mode, pick up the remaining code units in order to find+the end of the character, even when caseless. */++#ifdef SUPPORT_UNICODE+if (utf)+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (c >= 0xc0) GETUTF8INC(c, p);+#elif PCRE2_CODE_UNIT_WIDTH == 16+ if ((c & 0xfc00) == 0xd800) GETUTF16INC(c, p);+#endif+ }+#endif /* SUPPORT_UNICODE */++/* If caseless, handle the other case of the character. */++if (caseless)+ {+#ifdef SUPPORT_UNICODE+ if (utf || ucp)+ {+ c = UCD_OTHERCASE(c);+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (utf)+ {+ PCRE2_UCHAR buff[6];+ (void)PRIV(ord2utf)(c, buff);+ SET_BIT(buff[0]);+ }+ else if (c < 256) SET_BIT(c);+#else /* 16-bit or 32-bit mode */+ if (c > 0xff) SET_BIT(0xff); else SET_BIT(c);+#endif+ }++ else+#endif /* SUPPORT_UNICODE */++ /* Not UTF or UCP */++ if (MAX_255(c)) SET_BIT(re->tables[fcc_offset + c]);+ }++return p;+}++++/*************************************************+* Set bits for a positive character type *+*************************************************/++/* This function sets starting bits for a character type. In UTF-8 mode, we can+only do a direct setting for bytes less than 128, as otherwise there can be+confusion with bytes in the middle of UTF-8 characters. In a "traditional"+environment, the tables will only recognize ASCII characters anyway, but in at+least one Windows environment, some higher bytes bits were set in the tables.+So we deal with that case by considering the UTF-8 encoding.++Arguments:+ re the regex block+ cbit type the type of character wanted+ table_limit 32 for non-UTF-8; 16 for UTF-8++Returns: nothing+*/++static void+set_type_bits(pcre2_real_code *re, int cbit_type, unsigned int table_limit)+{+uint32_t c;+for (c = 0; c < table_limit; c++)+ re->start_bitmap[c] |= re->tables[c+cbits_offset+cbit_type];+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+if (table_limit == 32) return;+for (c = 128; c < 256; c++)+ {+ if ((re->tables[cbits_offset + c/8] & (1u << (c&7))) != 0)+ {+ PCRE2_UCHAR buff[6];+ (void)PRIV(ord2utf)(c, buff);+ SET_BIT(buff[0]);+ }+ }+#endif /* UTF-8 */+}+++/*************************************************+* Set bits for a negative character type *+*************************************************/++/* This function sets starting bits for a negative character type such as \D.+In UTF-8 mode, we can only do a direct setting for bytes less than 128, as+otherwise there can be confusion with bytes in the middle of UTF-8 characters.+Unlike in the positive case, where we can set appropriate starting bits for+specific high-valued UTF-8 characters, in this case we have to set the bits for+all high-valued characters. The lowest is 0xc2, but we overkill by starting at+0xc0 (192) for simplicity.++Arguments:+ re the regex block+ cbit type the type of character wanted+ table_limit 32 for non-UTF-8; 16 for UTF-8++Returns: nothing+*/++static void+set_nottype_bits(pcre2_real_code *re, int cbit_type, unsigned int table_limit)+{+uint32_t c;+for (c = 0; c < table_limit; c++)+ re->start_bitmap[c] |= ~(re->tables[c+cbits_offset+cbit_type]);+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+if (table_limit != 32) for (c = 24; c < 32; c++) re->start_bitmap[c] = 0xff;+#endif+}++++/*************************************************+* Create bitmap of starting code units *+*************************************************/++/* This function scans a compiled unanchored expression recursively and+attempts to build a bitmap of the set of possible starting code units whose+values are less than 256. In 16-bit and 32-bit mode, values above 255 all cause+the 255 bit to be set. When calling set[_not]_type_bits() in UTF-8 (sic) mode+we pass a value of 16 rather than 32 as the final argument. (See comments in+those functions for the reason.)++The SSB_CONTINUE return is useful for parenthesized groups in patterns such as+(a*)b where the group provides some optional starting code units but scanning+must continue at the outer level to find at least one mandatory code unit. At+the outermost level, this function fails unless the result is SSB_DONE.++We restrict recursion (for nested groups) to 1000 to avoid stack overflow+issues.++Arguments:+ re points to the compiled regex block+ code points to an expression+ utf TRUE if in UTF mode+ ucp TRUE if in UCP mode+ depthptr pointer to recurse depth++Returns: SSB_FAIL => Failed to find any starting code units+ SSB_DONE => Found mandatory starting code units+ SSB_CONTINUE => Found optional starting code units+ SSB_UNKNOWN => Hit an unrecognized opcode+ SSB_TOODEEP => Recursion is too deep+*/++static int+set_start_bits(pcre2_real_code *re, PCRE2_SPTR code, BOOL utf, BOOL ucp,+ int *depthptr)+{+uint32_t c;+int yield = SSB_DONE;++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+int table_limit = utf? 16:32;+#else+int table_limit = 32;+#endif++*depthptr += 1;+if (*depthptr > 1000) return SSB_TOODEEP;++do+ {+ BOOL try_next = TRUE;+ PCRE2_SPTR tcode = code + 1 + LINK_SIZE;++ if (*code == OP_CBRA || *code == OP_SCBRA ||+ *code == OP_CBRAPOS || *code == OP_SCBRAPOS) tcode += IMM2_SIZE;++ while (try_next) /* Loop for items in this branch */+ {+ int rc;+ uint8_t *classmap = NULL;+#ifdef SUPPORT_WIDE_CHARS+ PCRE2_UCHAR xclassflags;+#endif++ switch(*tcode)+ {+ /* If we reach something we don't understand, it means a new opcode has+ been created that hasn't been added to this function. Hopefully this+ problem will be discovered during testing. */++ default:+ return SSB_UNKNOWN;++ /* Fail for a valid opcode that implies no starting bits. */++ case OP_ACCEPT:+ case OP_ASSERT_ACCEPT:+ case OP_ALLANY:+ case OP_ANY:+ case OP_ANYBYTE:+ case OP_CIRCM:+ case OP_CLOSE:+ case OP_COMMIT:+ case OP_COMMIT_ARG:+ case OP_COND:+ case OP_CREF:+ case OP_FALSE:+ case OP_TRUE:+ case OP_DNCREF:+ case OP_DNREF:+ case OP_DNREFI:+ case OP_DNRREF:+ case OP_DOLL:+ case OP_DOLLM:+ case OP_END:+ case OP_EOD:+ case OP_EODN:+ case OP_EXTUNI:+ case OP_FAIL:+ case OP_MARK:+ case OP_NOT:+ case OP_NOTEXACT:+ case OP_NOTEXACTI:+ case OP_NOTI:+ case OP_NOTMINPLUS:+ case OP_NOTMINPLUSI:+ case OP_NOTMINQUERY:+ case OP_NOTMINQUERYI:+ case OP_NOTMINSTAR:+ case OP_NOTMINSTARI:+ case OP_NOTMINUPTO:+ case OP_NOTMINUPTOI:+ case OP_NOTPLUS:+ case OP_NOTPLUSI:+ case OP_NOTPOSPLUS:+ case OP_NOTPOSPLUSI:+ case OP_NOTPOSQUERY:+ case OP_NOTPOSQUERYI:+ case OP_NOTPOSSTAR:+ case OP_NOTPOSSTARI:+ case OP_NOTPOSUPTO:+ case OP_NOTPOSUPTOI:+ case OP_NOTPROP:+ case OP_NOTQUERY:+ case OP_NOTQUERYI:+ case OP_NOTSTAR:+ case OP_NOTSTARI:+ case OP_NOTUPTO:+ case OP_NOTUPTOI:+ case OP_NOT_HSPACE:+ case OP_NOT_VSPACE:+ case OP_PRUNE:+ case OP_PRUNE_ARG:+ case OP_RECURSE:+ case OP_REF:+ case OP_REFI:+ case OP_REVERSE:+ case OP_RREF:+ case OP_SCOND:+ case OP_SET_SOM:+ case OP_SKIP:+ case OP_SKIP_ARG:+ case OP_SOD:+ case OP_SOM:+ case OP_THEN:+ case OP_THEN_ARG:+ return SSB_FAIL;++ /* OP_CIRC happens only at the start of an anchored branch (multiline ^+ uses OP_CIRCM). Skip over it. */++ case OP_CIRC:+ tcode += PRIV(OP_lengths)[OP_CIRC];+ break;++ /* A "real" property test implies no starting bits, but the fake property+ PT_CLIST identifies a list of characters. These lists are short, as they+ are used for characters with more than one "other case", so there is no+ point in recognizing them for OP_NOTPROP. */++ case OP_PROP:+ if (tcode[1] != PT_CLIST) return SSB_FAIL;+ {+ const uint32_t *p = PRIV(ucd_caseless_sets) + tcode[2];+ while ((c = *p++) < NOTACHAR)+ {+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (utf)+ {+ PCRE2_UCHAR buff[6];+ (void)PRIV(ord2utf)(c, buff);+ c = buff[0];+ }+#endif+ if (c > 0xff) SET_BIT(0xff); else SET_BIT(c);+ }+ }+ try_next = FALSE;+ break;++ /* We can ignore word boundary tests. */++ case OP_WORD_BOUNDARY:+ case OP_NOT_WORD_BOUNDARY:+ tcode++;+ break;++ /* If we hit a bracket or a positive lookahead assertion, recurse to set+ bits from within the subpattern. If it can't find anything, we have to+ give up. If it finds some mandatory character(s), we are done for this+ branch. Otherwise, carry on scanning after the subpattern. */++ case OP_BRA:+ case OP_SBRA:+ case OP_CBRA:+ case OP_SCBRA:+ case OP_BRAPOS:+ case OP_SBRAPOS:+ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_ASSERT:+ case OP_ASSERT_NA:+ rc = set_start_bits(re, tcode, utf, ucp, depthptr);+ if (rc == SSB_DONE)+ {+ try_next = FALSE;+ }+ else if (rc == SSB_CONTINUE)+ {+ do tcode += GET(tcode, 1); while (*tcode == OP_ALT);+ tcode += 1 + LINK_SIZE;+ }+ else return rc; /* FAIL, UNKNOWN, or TOODEEP */+ break;++ /* If we hit ALT or KET, it means we haven't found anything mandatory in+ this branch, though we might have found something optional. For ALT, we+ continue with the next alternative, but we have to arrange that the final+ result from subpattern is SSB_CONTINUE rather than SSB_DONE. For KET,+ return SSB_CONTINUE: if this is the top level, that indicates failure,+ but after a nested subpattern, it causes scanning to continue. */++ case OP_ALT:+ yield = SSB_CONTINUE;+ try_next = FALSE;+ break;++ case OP_KET:+ case OP_KETRMAX:+ case OP_KETRMIN:+ case OP_KETRPOS:+ return SSB_CONTINUE;++ /* Skip over callout */++ case OP_CALLOUT:+ tcode += PRIV(OP_lengths)[OP_CALLOUT];+ break;++ case OP_CALLOUT_STR:+ tcode += GET(tcode, 1 + 2*LINK_SIZE);+ break;++ /* Skip over lookbehind and negative lookahead assertions */++ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERTBACK_NA:+ do tcode += GET(tcode, 1); while (*tcode == OP_ALT);+ tcode += 1 + LINK_SIZE;+ break;++ /* BRAZERO does the bracket, but carries on. */++ case OP_BRAZERO:+ case OP_BRAMINZERO:+ case OP_BRAPOSZERO:+ rc = set_start_bits(re, ++tcode, utf, ucp, depthptr);+ if (rc == SSB_FAIL || rc == SSB_UNKNOWN || rc == SSB_TOODEEP) return rc;+ do tcode += GET(tcode,1); while (*tcode == OP_ALT);+ tcode += 1 + LINK_SIZE;+ break;++ /* SKIPZERO skips the bracket. */++ case OP_SKIPZERO:+ tcode++;+ do tcode += GET(tcode,1); while (*tcode == OP_ALT);+ tcode += 1 + LINK_SIZE;+ break;++ /* Single-char * or ? sets the bit and tries the next item */++ case OP_STAR:+ case OP_MINSTAR:+ case OP_POSSTAR:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_POSQUERY:+ tcode = set_table_bit(re, tcode + 1, FALSE, utf, ucp);+ break;++ case OP_STARI:+ case OP_MINSTARI:+ case OP_POSSTARI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_POSQUERYI:+ tcode = set_table_bit(re, tcode + 1, TRUE, utf, ucp);+ break;++ /* Single-char upto sets the bit and tries the next */++ case OP_UPTO:+ case OP_MINUPTO:+ case OP_POSUPTO:+ tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, FALSE, utf, ucp);+ break;++ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_POSUPTOI:+ tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, TRUE, utf, ucp);+ break;++ /* At least one single char sets the bit and stops */++ case OP_EXACT:+ tcode += IMM2_SIZE;+ /* Fall through */+ case OP_CHAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_POSPLUS:+ (void)set_table_bit(re, tcode + 1, FALSE, utf, ucp);+ try_next = FALSE;+ break;++ case OP_EXACTI:+ tcode += IMM2_SIZE;+ /* Fall through */+ case OP_CHARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_POSPLUSI:+ (void)set_table_bit(re, tcode + 1, TRUE, utf, ucp);+ try_next = FALSE;+ break;++ /* Special spacing and line-terminating items. These recognize specific+ lists of characters. The difference between VSPACE and ANYNL is that the+ latter can match the two-character CRLF sequence, but that is not+ relevant for finding the first character, so their code here is+ identical. */++ case OP_HSPACE:+ SET_BIT(CHAR_HT);+ SET_BIT(CHAR_SPACE);++ /* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set+ the bits for 0xA0 and for code units >= 255, independently of UTF. */++#if PCRE2_CODE_UNIT_WIDTH != 8+ SET_BIT(0xA0);+ SET_BIT(0xFF);+#else+ /* For the 8-bit library in UTF-8 mode, set the bits for the first code+ units of horizontal space characters. */++#ifdef SUPPORT_UNICODE+ if (utf)+ {+ SET_BIT(0xC2); /* For U+00A0 */+ SET_BIT(0xE1); /* For U+1680, U+180E */+ SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */+ SET_BIT(0xE3); /* For U+3000 */+ }+ else+#endif+ /* For the 8-bit library not in UTF-8 mode, set the bit for 0xA0, unless+ the code is EBCDIC. */+ {+#ifndef EBCDIC+ SET_BIT(0xA0);+#endif /* Not EBCDIC */+ }+#endif /* 8-bit support */++ try_next = FALSE;+ break;++ case OP_ANYNL:+ case OP_VSPACE:+ SET_BIT(CHAR_LF);+ SET_BIT(CHAR_VT);+ SET_BIT(CHAR_FF);+ SET_BIT(CHAR_CR);++ /* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set+ the bits for NEL and for code units >= 255, independently of UTF. */++#if PCRE2_CODE_UNIT_WIDTH != 8+ SET_BIT(CHAR_NEL);+ SET_BIT(0xFF);+#else+ /* For the 8-bit library in UTF-8 mode, set the bits for the first code+ units of vertical space characters. */++#ifdef SUPPORT_UNICODE+ if (utf)+ {+ SET_BIT(0xC2); /* For U+0085 (NEL) */+ SET_BIT(0xE2); /* For U+2028, U+2029 */+ }+ else+#endif+ /* For the 8-bit library not in UTF-8 mode, set the bit for NEL. */+ {+ SET_BIT(CHAR_NEL);+ }+#endif /* 8-bit support */++ try_next = FALSE;+ break;++ /* Single character types set the bits and stop. Note that if PCRE2_UCP+ is set, we do not see these opcodes because \d etc are converted to+ properties. Therefore, these apply in the case when only characters less+ than 256 are recognized to match the types. */++ case OP_NOT_DIGIT:+ set_nottype_bits(re, cbit_digit, table_limit);+ try_next = FALSE;+ break;++ case OP_DIGIT:+ set_type_bits(re, cbit_digit, table_limit);+ try_next = FALSE;+ break;++ case OP_NOT_WHITESPACE:+ set_nottype_bits(re, cbit_space, table_limit);+ try_next = FALSE;+ break;++ case OP_WHITESPACE:+ set_type_bits(re, cbit_space, table_limit);+ try_next = FALSE;+ break;++ case OP_NOT_WORDCHAR:+ set_nottype_bits(re, cbit_word, table_limit);+ try_next = FALSE;+ break;++ case OP_WORDCHAR:+ set_type_bits(re, cbit_word, table_limit);+ try_next = FALSE;+ break;++ /* One or more character type fudges the pointer and restarts, knowing+ it will hit a single character type and stop there. */++ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEPOSPLUS:+ tcode++;+ break;++ case OP_TYPEEXACT:+ tcode += 1 + IMM2_SIZE;+ break;++ /* Zero or more repeats of character types set the bits and then+ try again. */++ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEPOSUPTO:+ tcode += IMM2_SIZE; /* Fall through */++ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPOSSTAR:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSQUERY:+ switch(tcode[1])+ {+ default:+ case OP_ANY:+ case OP_ALLANY:+ return SSB_FAIL;++ case OP_HSPACE:+ SET_BIT(CHAR_HT);+ SET_BIT(CHAR_SPACE);++ /* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set+ the bits for 0xA0 and for code units >= 255, independently of UTF. */++#if PCRE2_CODE_UNIT_WIDTH != 8+ SET_BIT(0xA0);+ SET_BIT(0xFF);+#else+ /* For the 8-bit library in UTF-8 mode, set the bits for the first code+ units of horizontal space characters. */++#ifdef SUPPORT_UNICODE+ if (utf)+ {+ SET_BIT(0xC2); /* For U+00A0 */+ SET_BIT(0xE1); /* For U+1680, U+180E */+ SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */+ SET_BIT(0xE3); /* For U+3000 */+ }+ else+#endif+ /* For the 8-bit library not in UTF-8 mode, set the bit for 0xA0, unless+ the code is EBCDIC. */+ {+#ifndef EBCDIC+ SET_BIT(0xA0);+#endif /* Not EBCDIC */+ }+#endif /* 8-bit support */+ break;++ case OP_ANYNL:+ case OP_VSPACE:+ SET_BIT(CHAR_LF);+ SET_BIT(CHAR_VT);+ SET_BIT(CHAR_FF);+ SET_BIT(CHAR_CR);++ /* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set+ the bits for NEL and for code units >= 255, independently of UTF. */++#if PCRE2_CODE_UNIT_WIDTH != 8+ SET_BIT(CHAR_NEL);+ SET_BIT(0xFF);+#else+ /* For the 8-bit library in UTF-8 mode, set the bits for the first code+ units of vertical space characters. */++#ifdef SUPPORT_UNICODE+ if (utf)+ {+ SET_BIT(0xC2); /* For U+0085 (NEL) */+ SET_BIT(0xE2); /* For U+2028, U+2029 */+ }+ else+#endif+ /* For the 8-bit library not in UTF-8 mode, set the bit for NEL. */+ {+ SET_BIT(CHAR_NEL);+ }+#endif /* 8-bit support */+ break;++ case OP_NOT_DIGIT:+ set_nottype_bits(re, cbit_digit, table_limit);+ break;++ case OP_DIGIT:+ set_type_bits(re, cbit_digit, table_limit);+ break;++ case OP_NOT_WHITESPACE:+ set_nottype_bits(re, cbit_space, table_limit);+ break;++ case OP_WHITESPACE:+ set_type_bits(re, cbit_space, table_limit);+ break;++ case OP_NOT_WORDCHAR:+ set_nottype_bits(re, cbit_word, table_limit);+ break;++ case OP_WORDCHAR:+ set_type_bits(re, cbit_word, table_limit);+ break;+ }++ tcode += 2;+ break;++ /* Extended class: if there are any property checks, or if this is a+ negative XCLASS without a map, give up. If there are no property checks,+ there must be wide characters on the XCLASS list, because otherwise an+ XCLASS would not have been created. This means that code points >= 255+ are potential starters. In the UTF-8 case we can scan them and set bits+ for the relevant leading bytes. */++#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+ xclassflags = tcode[1 + LINK_SIZE];+ if ((xclassflags & XCL_HASPROP) != 0 ||+ (xclassflags & (XCL_MAP|XCL_NOT)) == XCL_NOT)+ return SSB_FAIL;++ /* We have a positive XCLASS or a negative one without a map. Set up the+ map pointer if there is one, and fall through. */++ classmap = ((xclassflags & XCL_MAP) == 0)? NULL :+ (uint8_t *)(tcode + 1 + LINK_SIZE + 1);++ /* In UTF-8 mode, scan the character list and set bits for leading bytes,+ then jump to handle the map. */++#if PCRE2_CODE_UNIT_WIDTH == 8+ if (utf && (xclassflags & XCL_NOT) == 0)+ {+ PCRE2_UCHAR b, e;+ PCRE2_SPTR p = tcode + 1 + LINK_SIZE + 1 + ((classmap == NULL)? 0:32);+ tcode += GET(tcode, 1);++ for (;;) switch (*p++)+ {+ case XCL_SINGLE:+ b = *p++;+ while ((*p & 0xc0) == 0x80) p++;+ re->start_bitmap[b/8] |= (1u << (b&7));+ break;++ case XCL_RANGE:+ b = *p++;+ while ((*p & 0xc0) == 0x80) p++;+ e = *p++;+ while ((*p & 0xc0) == 0x80) p++;+ for (; b <= e; b++)+ re->start_bitmap[b/8] |= (1u << (b&7));+ break;++ case XCL_END:+ goto HANDLE_CLASSMAP;++ default:+ return SSB_UNKNOWN; /* Internal error, should not occur */+ }+ }+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */+#endif /* SUPPORT_WIDE_CHARS */++ /* It seems that the fall through comment must be outside the #ifdef if+ it is to avoid the gcc compiler warning. */++ /* Fall through */++ /* Enter here for a negative non-XCLASS. In the 8-bit library, if we are+ in UTF mode, any byte with a value >= 0xc4 is a potentially valid starter+ because it starts a character with a value > 255. In 8-bit non-UTF mode,+ there is no difference between CLASS and NCLASS. In all other wide+ character modes, set the 0xFF bit to indicate code units >= 255. */++ case OP_NCLASS:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (utf)+ {+ re->start_bitmap[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */+ memset(re->start_bitmap+25, 0xff, 7); /* Bits for 0xc9 - 0xff */+ }+#elif PCRE2_CODE_UNIT_WIDTH != 8+ SET_BIT(0xFF); /* For characters >= 255 */+#endif+ /* Fall through */++ /* Enter here for a positive non-XCLASS. If we have fallen through from+ an XCLASS, classmap will already be set; just advance the code pointer.+ Otherwise, set up classmap for a a non-XCLASS and advance past it. */++ case OP_CLASS:+ if (*tcode == OP_XCLASS) tcode += GET(tcode, 1); else+ {+ classmap = (uint8_t *)(++tcode);+ tcode += 32 / sizeof(PCRE2_UCHAR);+ }++ /* When wide characters are supported, classmap may be NULL. In UTF-8+ (sic) mode, the bits in a class bit map correspond to character values,+ not to byte values. However, the bit map we are constructing is for byte+ values. So we have to do a conversion for characters whose code point is+ greater than 127. In fact, there are only two possible starting bytes for+ characters in the range 128 - 255. */++#if defined SUPPORT_WIDE_CHARS && PCRE2_CODE_UNIT_WIDTH == 8+ HANDLE_CLASSMAP:+#endif+ if (classmap != NULL)+ {+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8+ if (utf)+ {+ for (c = 0; c < 16; c++) re->start_bitmap[c] |= classmap[c];+ for (c = 128; c < 256; c++)+ {+ if ((classmap[c/8] & (1u << (c&7))) != 0)+ {+ int d = (c >> 6) | 0xc0; /* Set bit for this starter */+ re->start_bitmap[d/8] |= (1u << (d&7)); /* and then skip on to the */+ c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */+ }+ }+ }+ else+#endif+ /* In all modes except UTF-8, the two bit maps are compatible. */++ {+ for (c = 0; c < 32; c++) re->start_bitmap[c] |= classmap[c];+ }+ }++ /* Act on what follows the class. For a zero minimum repeat, continue;+ otherwise stop processing. */++ switch (*tcode)+ {+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSSTAR:+ case OP_CRPOSQUERY:+ tcode++;+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ if (GET2(tcode, 1) == 0) tcode += 1 + 2 * IMM2_SIZE;+ else try_next = FALSE;+ break;++ default:+ try_next = FALSE;+ break;+ }+ break; /* End of class handling case */+ } /* End of switch for opcodes */+ } /* End of try_next loop */++ code += GET(code, 1); /* Advance to next branch */+ }+while (*code == OP_ALT);++return yield;+}++++/*************************************************+* Study a compiled expression *+*************************************************/++/* This function is handed a compiled expression that it must study to produce+information that will speed up the matching.++Argument:+ re points to the compiled expression++Returns: 0 normally; non-zero should never normally occur+ 1 unknown opcode in set_start_bits+ 2 missing capturing bracket+ 3 unknown opcode in find_minlength+*/++int+PRIV(study)(pcre2_real_code *re)+{+int count = 0;+PCRE2_UCHAR *code;+BOOL utf = (re->overall_options & PCRE2_UTF) != 0;+BOOL ucp = (re->overall_options & PCRE2_UCP) != 0;++/* Find start of compiled code */++code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) ++ re->name_entry_size * re->name_count;++/* For a pattern that has a first code unit, or a multiline pattern that+matches only at "line start", there is no point in seeking a list of starting+code units. */++if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)+ {+ int depth = 0;+ int rc = set_start_bits(re, code, utf, ucp, &depth);+ if (rc == SSB_UNKNOWN) return 1;++ /* If a list of starting code units was set up, scan the list to see if only+ one or two were listed. Having only one listed is rare because usually a+ single starting code unit will have been recognized and PCRE2_FIRSTSET set.+ If two are listed, see if they are caseless versions of the same character;+ if so we can replace the list with a caseless first code unit. This gives+ better performance and is plausibly worth doing for patterns such as [Ww]ord+ or (word|WORD). */++ if (rc == SSB_DONE)+ {+ int i;+ int a = -1;+ int b = -1;+ uint8_t *p = re->start_bitmap;+ uint32_t flags = PCRE2_FIRSTMAPSET;++ for (i = 0; i < 256; p++, i += 8)+ {+ uint8_t x = *p;+ if (x != 0)+ {+ int c;+ uint8_t y = x & (~x + 1); /* Least significant bit */+ if (y != x) goto DONE; /* More than one bit set */++ /* In the 16-bit and 32-bit libraries, the bit for 0xff means "0xff and+ all wide characters", so we cannot use it here. */++#if PCRE2_CODE_UNIT_WIDTH != 8+ if (i == 248 && x == 0x80) goto DONE;+#endif++ /* Compute the character value */++ c = i;+ switch (x)+ {+ case 1: break;+ case 2: c += 1; break; case 4: c += 2; break;+ case 8: c += 3; break; case 16: c += 4; break;+ case 32: c += 5; break; case 64: c += 6; break;+ case 128: c += 7; break;+ }++ /* c contains the code unit value, in the range 0-255. In 8-bit UTF+ mode, only values < 128 can be used. In all the other cases, c is a+ character value. */++#if PCRE2_CODE_UNIT_WIDTH == 8+ if (utf && c > 127) goto DONE;+#endif+ if (a < 0) a = c; /* First one found, save in a */+ else if (b < 0) /* Second one found */+ {+ int d = TABLE_GET((unsigned int)c, re->tables + fcc_offset, c);++#ifdef SUPPORT_UNICODE+ if (utf || ucp)+ {+ if (UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */+ if (c > 127) d = UCD_OTHERCASE(c);+ }+#endif /* SUPPORT_UNICODE */++ if (d != a) goto DONE; /* Not the other case of a */+ b = c; /* Save second in b */+ }+ else goto DONE; /* More than two characters found */+ }+ }++ /* Replace the start code unit bits with a first code unit, but only if it+ is not the same as a required later code unit. This is because a search for+ a required code unit starts after an explicit first code unit, but at a+ code unit found from the bitmap. Patterns such as /a*a/ don't work+ if both the start unit and required unit are the same. */++ if (a >= 0 &&+ (+ (re->flags & PCRE2_LASTSET) == 0 ||+ (+ re->last_codeunit != (uint32_t)a &&+ (b < 0 || re->last_codeunit != (uint32_t)b)+ )+ ))+ {+ re->first_codeunit = a;+ flags = PCRE2_FIRSTSET;+ if (b >= 0) flags |= PCRE2_FIRSTCASELESS;+ }++ DONE:+ re->flags |= flags;+ }+ }++/* Find the minimum length of subject string. If the pattern can match an empty+string, the minimum length is already known. If the pattern contains (*ACCEPT)+all bets are off, and we don't even try to find a minimum length. If there are+more back references than the size of the vector we are going to cache them in,+do nothing. A pattern that complicated will probably take a long time to+analyze and may in any case turn out to be too complicated. Note that back+reference minima are held as 16-bit numbers. */++if ((re->flags & (PCRE2_MATCH_EMPTY|PCRE2_HASACCEPT)) == 0 &&+ re->top_backref <= MAX_CACHE_BACKREF)+ {+ int min;+ int backref_cache[MAX_CACHE_BACKREF+1];+ backref_cache[0] = 0; /* Highest one that is set */+ min = find_minlength(re, code, code, utf, NULL, &count, backref_cache);+ switch(min)+ {+ case -1: /* \C in UTF mode or over-complex regex */+ break; /* Leave minlength unchanged (will be zero) */++ case -2:+ return 2; /* missing capturing bracket */++ case -3:+ return 3; /* unrecognized opcode */++ default:+ re->minlength = (min > UINT16_MAX)? UINT16_MAX : min;+ break;+ }+ }++return 0;+}++/* End of pcre2_study.c */
+ src/c/pcre2/src/pcre2_substitute.c view
@@ -0,0 +1,987 @@+/*************************************************+* 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) 2016-2020 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++#include "pcre2_internal.h"++#define PTR_STACK_SIZE 20++#define SUBSTITUTE_OPTIONS \+ (PCRE2_SUBSTITUTE_EXTENDED|PCRE2_SUBSTITUTE_GLOBAL| \+ PCRE2_SUBSTITUTE_LITERAL|PCRE2_SUBSTITUTE_MATCHED| \+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH|PCRE2_SUBSTITUTE_REPLACEMENT_ONLY| \+ PCRE2_SUBSTITUTE_UNKNOWN_UNSET|PCRE2_SUBSTITUTE_UNSET_EMPTY)++++/*************************************************+* Find end of substitute text *+*************************************************/++/* In extended mode, we recognize ${name:+set text:unset text} and similar+constructions. This requires the identification of unescaped : and }+characters. This function scans for such. It must deal with nested ${+constructions. The pointer to the text is updated, either to the required end+character, or to where an error was detected.++Arguments:+ code points to the compiled expression (for options)+ ptrptr points to the pointer to the start of the text (updated)+ ptrend end of the whole string+ last TRUE if the last expected string (only } recognized)++Returns: 0 on success+ negative error code on failure+*/++static int+find_text_end(const pcre2_code *code, PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend,+ BOOL last)+{+int rc = 0;+uint32_t nestlevel = 0;+BOOL literal = FALSE;+PCRE2_SPTR ptr = *ptrptr;++for (; ptr < ptrend; ptr++)+ {+ if (literal)+ {+ if (ptr[0] == CHAR_BACKSLASH && ptr < ptrend - 1 && ptr[1] == CHAR_E)+ {+ literal = FALSE;+ ptr += 1;+ }+ }++ else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)+ {+ if (nestlevel == 0) goto EXIT;+ nestlevel--;+ }++ else if (*ptr == CHAR_COLON && !last && nestlevel == 0) goto EXIT;++ else if (*ptr == CHAR_DOLLAR_SIGN)+ {+ if (ptr < ptrend - 1 && ptr[1] == CHAR_LEFT_CURLY_BRACKET)+ {+ nestlevel++;+ ptr += 1;+ }+ }++ else if (*ptr == CHAR_BACKSLASH)+ {+ int erc;+ int errorcode;+ uint32_t ch;++ if (ptr < ptrend - 1) switch (ptr[1])+ {+ case CHAR_L:+ case CHAR_l:+ case CHAR_U:+ case CHAR_u:+ ptr += 1;+ continue;+ }++ ptr += 1; /* Must point after \ */+ erc = PRIV(check_escape)(&ptr, ptrend, &ch, &errorcode,+ code->overall_options, code->extra_options, FALSE, NULL);+ ptr -= 1; /* Back to last code unit of escape */+ if (errorcode != 0)+ {+ rc = errorcode;+ goto EXIT;+ }++ switch(erc)+ {+ case 0: /* Data character */+ case ESC_E: /* Isolated \E is ignored */+ break;++ case ESC_Q:+ literal = TRUE;+ break;++ default:+ rc = PCRE2_ERROR_BADREPESCAPE;+ goto EXIT;+ }+ }+ }++rc = PCRE2_ERROR_REPMISSINGBRACE; /* Terminator not found */++EXIT:+*ptrptr = ptr;+return rc;+}++++/*************************************************+* Match and substitute *+*************************************************/++/* This function applies a compiled re to a subject string and creates a new+string with substitutions. The first 7 arguments are the same as for+pcre2_match(). Either string length may be PCRE2_ZERO_TERMINATED.++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, or is NULL+ context points a PCRE2 context+ replacement points to the replacement string+ rlength length of replacement string+ buffer where to put the substituted string+ blength points to length of buffer; updated to length of string++Returns: >= 0 number of substitutions made+ < 0 an error code+ PCRE2_ERROR_BADREPLACEMENT means invalid use of $+*/++/* This macro checks for space in the buffer before copying into it. On+overflow, either give an error immediately, or keep on, accumulating the+length. */++#define CHECKMEMCPY(from,length) \+ { \+ if (!overflowed && lengthleft < length) \+ { \+ if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \+ overflowed = TRUE; \+ extra_needed = length - lengthleft; \+ } \+ else if (overflowed) \+ { \+ extra_needed += length; \+ } \+ else \+ { \+ memcpy(buffer + buff_offset, from, CU2BYTES(length)); \+ buff_offset += length; \+ lengthleft -= length; \+ } \+ }++/* Here's the function */++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substitute(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, PCRE2_SPTR replacement, PCRE2_SIZE rlength,+ PCRE2_UCHAR *buffer, PCRE2_SIZE *blength)+{+int rc;+int subs;+int forcecase = 0;+int forcecasereset = 0;+uint32_t ovector_count;+uint32_t goptions = 0;+uint32_t suboptions;+pcre2_match_data *internal_match_data = NULL;+BOOL escaped_literal = FALSE;+BOOL overflowed = FALSE;+BOOL use_existing_match;+BOOL replacement_only;+#ifdef SUPPORT_UNICODE+BOOL utf = (code->overall_options & PCRE2_UTF) != 0;+BOOL ucp = (code->overall_options & PCRE2_UCP) != 0;+#endif+PCRE2_UCHAR temp[6];+PCRE2_SPTR ptr;+PCRE2_SPTR repend;+PCRE2_SIZE extra_needed = 0;+PCRE2_SIZE buff_offset, buff_length, lengthleft, fraglength;+PCRE2_SIZE *ovector;+PCRE2_SIZE ovecsave[3];+pcre2_substitute_callout_block scb;++/* General initialization */++buff_offset = 0;+lengthleft = buff_length = *blength;+*blength = PCRE2_UNSET;+ovecsave[0] = ovecsave[1] = ovecsave[2] = PCRE2_UNSET;++/* Partial matching is not valid. This must come after setting *blength to+PCRE2_UNSET, so as not to imply an offset in the replacement. */++if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0)+ return PCRE2_ERROR_BADOPTION;++/* Check for using a match that has already happened. Note that the subject+pointer in the match data may be NULL after a no-match. */++use_existing_match = ((options & PCRE2_SUBSTITUTE_MATCHED) != 0);+replacement_only = ((options & PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) != 0);++/* If starting from an existing match, there must be an externally provided+match data block. We create an internal match_data block in two cases: (a) an+external one is not supplied (and we are not starting from an existing match);+(b) an existing match is to be used for the first substitution. In the latter+case, we copy the existing match into the internal block. This ensures that no+changes are made to the existing match data block. */++if (match_data == NULL)+ {+ pcre2_general_context *gcontext;+ if (use_existing_match) return PCRE2_ERROR_NULL;+ gcontext = (mcontext == NULL)?+ (pcre2_general_context *)code :+ (pcre2_general_context *)mcontext;+ match_data = internal_match_data =+ pcre2_match_data_create_from_pattern(code, gcontext);+ if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY;+ }++else if (use_existing_match)+ {+ pcre2_general_context *gcontext = (mcontext == NULL)?+ (pcre2_general_context *)code :+ (pcre2_general_context *)mcontext;+ int pairs = (code->top_bracket + 1 < match_data->oveccount)?+ code->top_bracket + 1 : match_data->oveccount;+ internal_match_data = pcre2_match_data_create(match_data->oveccount,+ gcontext);+ if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY;+ memcpy(internal_match_data, match_data, offsetof(pcre2_match_data, ovector)+ + 2*pairs*sizeof(PCRE2_SIZE));+ match_data = internal_match_data;+ }++/* Remember ovector details */++ovector = pcre2_get_ovector_pointer(match_data);+ovector_count = pcre2_get_ovector_count(match_data);++/* Fixed things in the callout block */++scb.version = 0;+scb.input = subject;+scb.output = (PCRE2_SPTR)buffer;+scb.ovector = ovector;++/* Find lengths of zero-terminated strings and the end of the replacement. */++if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);+if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement);+repend = replacement + rlength;++/* Check UTF replacement string if necessary. */++#ifdef SUPPORT_UNICODE+if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)+ {+ rc = PRIV(valid_utf)(replacement, rlength, &(match_data->startchar));+ if (rc != 0)+ {+ match_data->leftchar = 0;+ goto EXIT;+ }+ }+#endif /* SUPPORT_UNICODE */++/* Save the substitute options and remove them from the match options. */++suboptions = options & SUBSTITUTE_OPTIONS;+options &= ~SUBSTITUTE_OPTIONS;++/* Error if the start match offset is greater than the length of the subject. */++if (start_offset > length)+ {+ match_data->leftchar = 0;+ rc = PCRE2_ERROR_BADOFFSET;+ goto EXIT;+ }++/* Copy up to the start offset, unless only the replacement is required. */++if (!replacement_only) CHECKMEMCPY(subject, start_offset);++/* Loop for global substituting. If PCRE2_SUBSTITUTE_MATCHED is set, the first+match is taken from the match_data that was passed in. */++subs = 0;+do+ {+ PCRE2_SPTR ptrstack[PTR_STACK_SIZE];+ uint32_t ptrstackptr = 0;++ if (use_existing_match)+ {+ rc = match_data->rc;+ use_existing_match = FALSE;+ }+ else rc = pcre2_match(code, subject, length, start_offset, options|goptions,+ match_data, mcontext);++#ifdef SUPPORT_UNICODE+ if (utf) options |= PCRE2_NO_UTF_CHECK; /* Only need to check once */+#endif++ /* Any error other than no match returns the error code. No match when not+ doing the special after-empty-match global rematch, or when at the end of the+ subject, breaks the global loop. Otherwise, advance the starting point by one+ character, copying it to the output, and try again. */++ if (rc < 0)+ {+ PCRE2_SIZE save_start;++ if (rc != PCRE2_ERROR_NOMATCH) goto EXIT;+ if (goptions == 0 || start_offset >= length) break;++ /* Advance by one code point. Then, if CRLF is a valid newline sequence and+ we have advanced into the middle of it, advance one more code point. In+ other words, do not start in the middle of CRLF, even if CR and LF on their+ own are valid newlines. */++ save_start = start_offset++;+ if (subject[start_offset-1] == CHAR_CR &&+ code->newline_convention != PCRE2_NEWLINE_CR &&+ code->newline_convention != PCRE2_NEWLINE_LF &&+ start_offset < length &&+ subject[start_offset] == CHAR_LF)+ start_offset++;++ /* Otherwise, in UTF mode, advance past any secondary code points. */++ else if ((code->overall_options & PCRE2_UTF) != 0)+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ while (start_offset < length && (subject[start_offset] & 0xc0) == 0x80)+ start_offset++;+#elif PCRE2_CODE_UNIT_WIDTH == 16+ while (start_offset < length &&+ (subject[start_offset] & 0xfc00) == 0xdc00)+ start_offset++;+#endif+ }++ /* Copy what we have advanced past (unless not required), reset the special+ global options, and continue to the next match. */++ fraglength = start_offset - save_start;+ if (!replacement_only) CHECKMEMCPY(subject + save_start, fraglength);+ goptions = 0;+ continue;+ }++ /* Handle a successful match. Matches that use \K to end before they start+ or start before the current point in the subject are not supported. */++ if (ovector[1] < ovector[0] || ovector[0] < start_offset)+ {+ rc = PCRE2_ERROR_BADSUBSPATTERN;+ goto EXIT;+ }++ /* Check for the same match as previous. This is legitimate after matching an+ empty string that starts after the initial match offset. We have tried again+ at the match point in case the pattern is one like /(?<=\G.)/ which can never+ match at its starting point, so running the match achieves the bumpalong. If+ we do get the same (null) match at the original match point, it isn't such a+ pattern, so we now do the empty string magic. In all other cases, a repeat+ match should never occur. */++ if (ovecsave[0] == ovector[0] && ovecsave[1] == ovector[1])+ {+ if (ovector[0] == ovector[1] && ovecsave[2] != start_offset)+ {+ goptions = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;+ ovecsave[2] = start_offset;+ continue; /* Back to the top of the loop */+ }+ rc = PCRE2_ERROR_INTERNAL_DUPMATCH;+ goto EXIT;+ }++ /* Count substitutions with a paranoid check for integer overflow; surely no+ real call to this function would ever hit this! */++ if (subs == INT_MAX)+ {+ rc = PCRE2_ERROR_TOOMANYREPLACE;+ goto EXIT;+ }+ subs++;++ /* Copy the text leading up to the match (unless not required), and remember+ where the insert begins and how many ovector pairs are set. */++ if (rc == 0) rc = ovector_count;+ fraglength = ovector[0] - start_offset;+ if (!replacement_only) CHECKMEMCPY(subject + start_offset, fraglength);+ scb.output_offsets[0] = buff_offset;+ scb.oveccount = rc;++ /* Process the replacement string. If the entire replacement is literal, just+ copy it with length check. */++ ptr = replacement;+ if ((suboptions & PCRE2_SUBSTITUTE_LITERAL) != 0)+ {+ CHECKMEMCPY(ptr, rlength);+ }++ /* Within a non-literal replacement, which must be scanned character by+ character, local literal mode can be set by \Q, but only in extended mode+ when backslashes are being interpreted. In extended mode we must handle+ nested substrings that are to be reprocessed. */++ else for (;;)+ {+ uint32_t ch;+ unsigned int chlen;++ /* If at the end of a nested substring, pop the stack. */++ if (ptr >= repend)+ {+ if (ptrstackptr == 0) break; /* End of replacement string */+ repend = ptrstack[--ptrstackptr];+ ptr = ptrstack[--ptrstackptr];+ continue;+ }++ /* Handle the next character */++ if (escaped_literal)+ {+ if (ptr[0] == CHAR_BACKSLASH && ptr < repend - 1 && ptr[1] == CHAR_E)+ {+ escaped_literal = FALSE;+ ptr += 2;+ continue;+ }+ goto LOADLITERAL;+ }++ /* Not in literal mode. */++ if (*ptr == CHAR_DOLLAR_SIGN)+ {+ int group, n;+ uint32_t special = 0;+ BOOL inparens;+ BOOL star;+ PCRE2_SIZE sublength;+ PCRE2_SPTR text1_start = NULL;+ PCRE2_SPTR text1_end = NULL;+ PCRE2_SPTR text2_start = NULL;+ PCRE2_SPTR text2_end = NULL;+ PCRE2_UCHAR next;+ PCRE2_UCHAR name[33];++ if (++ptr >= repend) goto BAD;+ if ((next = *ptr) == CHAR_DOLLAR_SIGN) goto LOADLITERAL;++ group = -1;+ n = 0;+ inparens = FALSE;+ star = FALSE;++ if (next == CHAR_LEFT_CURLY_BRACKET)+ {+ if (++ptr >= repend) goto BAD;+ next = *ptr;+ inparens = TRUE;+ }++ if (next == CHAR_ASTERISK)+ {+ if (++ptr >= repend) goto BAD;+ next = *ptr;+ star = TRUE;+ }++ if (!star && next >= CHAR_0 && next <= CHAR_9)+ {+ group = next - CHAR_0;+ while (++ptr < repend)+ {+ next = *ptr;+ if (next < CHAR_0 || next > CHAR_9) break;+ group = group * 10 + next - CHAR_0;++ /* A check for a number greater than the hightest captured group+ is sufficient here; no need for a separate overflow check. If unknown+ groups are to be treated as unset, just skip over any remaining+ digits and carry on. */++ if (group > code->top_bracket)+ {+ if ((suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)+ {+ while (++ptr < repend && *ptr >= CHAR_0 && *ptr <= CHAR_9);+ break;+ }+ else+ {+ rc = PCRE2_ERROR_NOSUBSTRING;+ goto PTREXIT;+ }+ }+ }+ }+ else+ {+ const uint8_t *ctypes = code->tables + ctypes_offset;+ while (MAX_255(next) && (ctypes[next] & ctype_word) != 0)+ {+ name[n++] = next;+ if (n > 32) goto BAD;+ if (++ptr >= repend) break;+ next = *ptr;+ }+ if (n == 0) goto BAD;+ name[n] = 0;+ }++ /* In extended mode we recognize ${name:+set text:unset text} and+ ${name:-default text}. */++ if (inparens)+ {+ if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 &&+ !star && ptr < repend - 2 && next == CHAR_COLON)+ {+ special = *(++ptr);+ if (special != CHAR_PLUS && special != CHAR_MINUS)+ {+ rc = PCRE2_ERROR_BADSUBSTITUTION;+ goto PTREXIT;+ }++ text1_start = ++ptr;+ rc = find_text_end(code, &ptr, repend, special == CHAR_MINUS);+ if (rc != 0) goto PTREXIT;+ text1_end = ptr;++ if (special == CHAR_PLUS && *ptr == CHAR_COLON)+ {+ text2_start = ++ptr;+ rc = find_text_end(code, &ptr, repend, TRUE);+ if (rc != 0) goto PTREXIT;+ text2_end = ptr;+ }+ }++ else+ {+ if (ptr >= repend || *ptr != CHAR_RIGHT_CURLY_BRACKET)+ {+ rc = PCRE2_ERROR_REPMISSINGBRACE;+ goto PTREXIT;+ }+ }++ ptr++;+ }++ /* Have found a syntactically correct group number or name, or *name.+ Only *MARK is currently recognized. */++ if (star)+ {+ if (PRIV(strcmp_c8)(name, STRING_MARK) == 0)+ {+ PCRE2_SPTR mark = pcre2_get_mark(match_data);+ if (mark != NULL)+ {+ PCRE2_SPTR mark_start = mark;+ while (*mark != 0) mark++;+ fraglength = mark - mark_start;+ CHECKMEMCPY(mark_start, fraglength);+ }+ }+ else goto BAD;+ }++ /* Substitute the contents of a group. We don't use substring_copy+ functions any more, in order to support case forcing. */++ else+ {+ PCRE2_SPTR subptr, subptrend;++ /* Find a number for a named group. In case there are duplicate names,+ search for the first one that is set. If the name is not found when+ PCRE2_SUBSTITUTE_UNKNOWN_EMPTY is set, set the group number to a+ non-existent group. */++ if (group < 0)+ {+ PCRE2_SPTR first, last, entry;+ rc = pcre2_substring_nametable_scan(code, name, &first, &last);+ if (rc == PCRE2_ERROR_NOSUBSTRING &&+ (suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)+ {+ group = code->top_bracket + 1;+ }+ else+ {+ if (rc < 0) goto PTREXIT;+ for (entry = first; entry <= last; entry += rc)+ {+ uint32_t ng = GET2(entry, 0);+ if (ng < ovector_count)+ {+ if (group < 0) group = ng; /* First in ovector */+ if (ovector[ng*2] != PCRE2_UNSET)+ {+ group = ng; /* First that is set */+ break;+ }+ }+ }++ /* If group is still negative, it means we did not find a group+ that is in the ovector. Just set the first group. */++ if (group < 0) group = GET2(first, 0);+ }+ }++ /* We now have a group that is identified by number. Find the length of+ the captured string. If a group in a non-special substitution is unset+ when PCRE2_SUBSTITUTE_UNSET_EMPTY is set, substitute nothing. */++ rc = pcre2_substring_length_bynumber(match_data, group, &sublength);+ if (rc < 0)+ {+ if (rc == PCRE2_ERROR_NOSUBSTRING &&+ (suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)+ {+ rc = PCRE2_ERROR_UNSET;+ }+ if (rc != PCRE2_ERROR_UNSET) goto PTREXIT; /* Non-unset errors */+ if (special == 0) /* Plain substitution */+ {+ if ((suboptions & PCRE2_SUBSTITUTE_UNSET_EMPTY) != 0) continue;+ goto PTREXIT; /* Else error */+ }+ }++ /* If special is '+' we have a 'set' and possibly an 'unset' text,+ both of which are reprocessed when used. If special is '-' we have a+ default text for when the group is unset; it must be reprocessed. */++ if (special != 0)+ {+ if (special == CHAR_MINUS)+ {+ if (rc == 0) goto LITERAL_SUBSTITUTE;+ text2_start = text1_start;+ text2_end = text1_end;+ }++ if (ptrstackptr >= PTR_STACK_SIZE) goto BAD;+ ptrstack[ptrstackptr++] = ptr;+ ptrstack[ptrstackptr++] = repend;++ if (rc == 0)+ {+ ptr = text1_start;+ repend = text1_end;+ }+ else+ {+ ptr = text2_start;+ repend = text2_end;+ }+ continue;+ }++ /* Otherwise we have a literal substitution of a group's contents. */++ LITERAL_SUBSTITUTE:+ subptr = subject + ovector[group*2];+ subptrend = subject + ovector[group*2 + 1];++ /* Substitute a literal string, possibly forcing alphabetic case. */++ while (subptr < subptrend)+ {+ GETCHARINCTEST(ch, subptr);+ if (forcecase != 0)+ {+#ifdef SUPPORT_UNICODE+ if (utf || ucp)+ {+ uint32_t type = UCD_CHARTYPE(ch);+ if (PRIV(ucp_gentype)[type] == ucp_L &&+ type != ((forcecase > 0)? ucp_Lu : ucp_Ll))+ ch = UCD_OTHERCASE(ch);+ }+ else+#endif+ {+ if (((code->tables + cbits_offset ++ ((forcecase > 0)? cbit_upper:cbit_lower)+ )[ch/8] & (1u << (ch%8))) == 0)+ ch = (code->tables + fcc_offset)[ch];+ }+ forcecase = forcecasereset;+ }++#ifdef SUPPORT_UNICODE+ if (utf) chlen = PRIV(ord2utf)(ch, temp); else+#endif+ {+ temp[0] = ch;+ chlen = 1;+ }+ CHECKMEMCPY(temp, chlen);+ }+ }+ }++ /* Handle an escape sequence in extended mode. We can use check_escape()+ to process \Q, \E, \c, \o, \x and \ followed by non-alphanumerics, but+ the case-forcing escapes are not supported in pcre2_compile() so must be+ recognized here. */++ else if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 &&+ *ptr == CHAR_BACKSLASH)+ {+ int errorcode;++ if (ptr < repend - 1) switch (ptr[1])+ {+ case CHAR_L:+ forcecase = forcecasereset = -1;+ ptr += 2;+ continue;++ case CHAR_l:+ forcecase = -1;+ forcecasereset = 0;+ ptr += 2;+ continue;++ case CHAR_U:+ forcecase = forcecasereset = 1;+ ptr += 2;+ continue;++ case CHAR_u:+ forcecase = 1;+ forcecasereset = 0;+ ptr += 2;+ continue;++ default:+ break;+ }++ ptr++; /* Point after \ */+ rc = PRIV(check_escape)(&ptr, repend, &ch, &errorcode,+ code->overall_options, code->extra_options, FALSE, NULL);+ if (errorcode != 0) goto BADESCAPE;++ switch(rc)+ {+ case ESC_E:+ forcecase = forcecasereset = 0;+ continue;++ case ESC_Q:+ escaped_literal = TRUE;+ continue;++ case 0: /* Data character */+ goto LITERAL;++ default:+ goto BADESCAPE;+ }+ }++ /* Handle a literal code unit */++ else+ {+ LOADLITERAL:+ GETCHARINCTEST(ch, ptr); /* Get character value, increment pointer */++ LITERAL:+ if (forcecase != 0)+ {+#ifdef SUPPORT_UNICODE+ if (utf || ucp)+ {+ uint32_t type = UCD_CHARTYPE(ch);+ if (PRIV(ucp_gentype)[type] == ucp_L &&+ type != ((forcecase > 0)? ucp_Lu : ucp_Ll))+ ch = UCD_OTHERCASE(ch);+ }+ else+#endif+ {+ if (((code->tables + cbits_offset ++ ((forcecase > 0)? cbit_upper:cbit_lower)+ )[ch/8] & (1u << (ch%8))) == 0)+ ch = (code->tables + fcc_offset)[ch];+ }+ forcecase = forcecasereset;+ }++#ifdef SUPPORT_UNICODE+ if (utf) chlen = PRIV(ord2utf)(ch, temp); else+#endif+ {+ temp[0] = ch;+ chlen = 1;+ }+ CHECKMEMCPY(temp, chlen);+ } /* End handling a literal code unit */+ } /* End of loop for scanning the replacement. */++ /* The replacement has been copied to the output, or its size has been+ remembered. Do the callout if there is one and we have done an actual+ replacement. */++ if (!overflowed && mcontext != NULL && mcontext->substitute_callout != NULL)+ {+ scb.subscount = subs;+ scb.output_offsets[1] = buff_offset;+ rc = mcontext->substitute_callout(&scb, mcontext->substitute_callout_data);++ /* A non-zero return means cancel this substitution. Instead, copy the+ matched string fragment. */++ if (rc != 0)+ {+ PCRE2_SIZE newlength = scb.output_offsets[1] - scb.output_offsets[0];+ PCRE2_SIZE oldlength = ovector[1] - ovector[0];++ buff_offset -= newlength;+ lengthleft += newlength;+ if (!replacement_only) CHECKMEMCPY(subject + ovector[0], oldlength);++ /* A negative return means do not do any more. */++ if (rc < 0) suboptions &= (~PCRE2_SUBSTITUTE_GLOBAL);+ }+ }++ /* Save the details of this match. See above for how this data is used. If we+ matched an empty string, do the magic for global matches. Update the start+ offset to point to the rest of the subject string. If we re-used an existing+ match for the first match, switch to the internal match data block. */++ ovecsave[0] = ovector[0];+ ovecsave[1] = ovector[1];+ ovecsave[2] = start_offset;++ goptions = (ovector[0] != ovector[1] || ovector[0] > start_offset)? 0 :+ PCRE2_ANCHORED|PCRE2_NOTEMPTY_ATSTART;+ start_offset = ovector[1];+ } while ((suboptions & PCRE2_SUBSTITUTE_GLOBAL) != 0); /* Repeat "do" loop */++/* Copy the rest of the subject unless not required, and terminate the output+with a binary zero. */++if (!replacement_only)+ {+ fraglength = length - start_offset;+ CHECKMEMCPY(subject + start_offset, fraglength);+ }++temp[0] = 0;+CHECKMEMCPY(temp, 1);++/* If overflowed is set it means the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set,+and matching has carried on after a full buffer, in order to compute the length+needed. Otherwise, an overflow generates an immediate error return. */++if (overflowed)+ {+ rc = PCRE2_ERROR_NOMEMORY;+ *blength = buff_length + extra_needed;+ }++/* After a successful execution, return the number of substitutions and set the+length of buffer used, excluding the trailing zero. */++else+ {+ rc = subs;+ *blength = buff_offset - 1;+ }++EXIT:+if (internal_match_data != NULL) pcre2_match_data_free(internal_match_data);+ else match_data->rc = rc;+return rc;++NOROOM:+rc = PCRE2_ERROR_NOMEMORY;+goto EXIT;++BAD:+rc = PCRE2_ERROR_BADREPLACEMENT;+goto PTREXIT;++BADESCAPE:+rc = PCRE2_ERROR_BADREPESCAPE;++PTREXIT:+*blength = (PCRE2_SIZE)(ptr - replacement);+goto EXIT;+}++/* End of pcre2_substitute.c */
+ src/c/pcre2/src/pcre2_substring.c view
@@ -0,0 +1,547 @@+/*************************************************+* 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) 2016-2018 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++#include "pcre2_internal.h"++++/*************************************************+* Copy named captured string to given buffer *+*************************************************/++/* This function copies a single captured substring into a given buffer,+identifying it by name. If the regex permits duplicate names, the first+substring that is set is chosen.++Arguments:+ match_data points to the match data+ stringname the name of the required substring+ buffer where to put the substring+ sizeptr the size of the buffer, updated to the size of the substring++Returns: if successful: zero+ if not successful, a negative error code:+ (1) an error from nametable_scan()+ (2) an error from copy_bynumber()+ (3) PCRE2_ERROR_UNAVAILABLE: no group is in ovector+ (4) PCRE2_ERROR_UNSET: all named groups in ovector are unset+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substring_copy_byname(pcre2_match_data *match_data, PCRE2_SPTR stringname,+ PCRE2_UCHAR *buffer, PCRE2_SIZE *sizeptr)+{+PCRE2_SPTR first, last, entry;+int failrc, entrysize;+if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)+ return PCRE2_ERROR_DFA_UFUNC;+entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,+ &first, &last);+if (entrysize < 0) return entrysize;+failrc = PCRE2_ERROR_UNAVAILABLE;+for (entry = first; entry <= last; entry += entrysize)+ {+ uint32_t n = GET2(entry, 0);+ if (n < match_data->oveccount)+ {+ if (match_data->ovector[n*2] != PCRE2_UNSET)+ return pcre2_substring_copy_bynumber(match_data, n, buffer, sizeptr);+ failrc = PCRE2_ERROR_UNSET;+ }+ }+return failrc;+}++++/*************************************************+* Copy numbered captured string to given buffer *+*************************************************/++/* This function copies a single captured substring into a given buffer,+identifying it by number.++Arguments:+ match_data points to the match data+ stringnumber the number of the required substring+ buffer where to put the substring+ sizeptr the size of the buffer, updated to the size of the substring++Returns: if successful: 0+ if not successful, a negative error code:+ PCRE2_ERROR_NOMEMORY: buffer too small+ PCRE2_ERROR_NOSUBSTRING: no such substring+ PCRE2_ERROR_UNAVAILABLE: ovector too small+ PCRE2_ERROR_UNSET: substring is not set+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substring_copy_bynumber(pcre2_match_data *match_data,+ uint32_t stringnumber, PCRE2_UCHAR *buffer, PCRE2_SIZE *sizeptr)+{+int rc;+PCRE2_SIZE size;+rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size);+if (rc < 0) return rc;+if (size + 1 > *sizeptr) return PCRE2_ERROR_NOMEMORY;+memcpy(buffer, match_data->subject + match_data->ovector[stringnumber*2],+ CU2BYTES(size));+buffer[size] = 0;+*sizeptr = size;+return 0;+}++++/*************************************************+* Extract named captured string *+*************************************************/++/* This function copies a single captured substring, identified by name, into+new memory. If the regex permits duplicate names, the first substring that is+set is chosen.++Arguments:+ match_data pointer to match_data+ stringname the name of the required substring+ stringptr where to put the pointer to the new memory+ sizeptr where to put the length of the substring++Returns: if successful: zero+ if not successful, a negative value:+ (1) an error from nametable_scan()+ (2) an error from get_bynumber()+ (3) PCRE2_ERROR_UNAVAILABLE: no group is in ovector+ (4) PCRE2_ERROR_UNSET: all named groups in ovector are unset+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substring_get_byname(pcre2_match_data *match_data,+ PCRE2_SPTR stringname, PCRE2_UCHAR **stringptr, PCRE2_SIZE *sizeptr)+{+PCRE2_SPTR first, last, entry;+int failrc, entrysize;+if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)+ return PCRE2_ERROR_DFA_UFUNC;+entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,+ &first, &last);+if (entrysize < 0) return entrysize;+failrc = PCRE2_ERROR_UNAVAILABLE;+for (entry = first; entry <= last; entry += entrysize)+ {+ uint32_t n = GET2(entry, 0);+ if (n < match_data->oveccount)+ {+ if (match_data->ovector[n*2] != PCRE2_UNSET)+ return pcre2_substring_get_bynumber(match_data, n, stringptr, sizeptr);+ failrc = PCRE2_ERROR_UNSET;+ }+ }+return failrc;+}++++/*************************************************+* Extract captured string to new memory *+*************************************************/++/* This function copies a single captured substring into a piece of new+memory.++Arguments:+ match_data points to match data+ stringnumber the number of the required substring+ stringptr where to put a pointer to the new memory+ sizeptr where to put the size of the substring++Returns: if successful: 0+ if not successful, a negative error code:+ PCRE2_ERROR_NOMEMORY: failed to get memory+ PCRE2_ERROR_NOSUBSTRING: no such substring+ PCRE2_ERROR_UNAVAILABLE: ovector too small+ PCRE2_ERROR_UNSET: substring is not set+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substring_get_bynumber(pcre2_match_data *match_data,+ uint32_t stringnumber, PCRE2_UCHAR **stringptr, PCRE2_SIZE *sizeptr)+{+int rc;+PCRE2_SIZE size;+PCRE2_UCHAR *yield;+rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size);+if (rc < 0) return rc;+yield = PRIV(memctl_malloc)(sizeof(pcre2_memctl) ++ (size + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)match_data);+if (yield == NULL) return PCRE2_ERROR_NOMEMORY;+yield = (PCRE2_UCHAR *)(((char *)yield) + sizeof(pcre2_memctl));+memcpy(yield, match_data->subject + match_data->ovector[stringnumber*2],+ CU2BYTES(size));+yield[size] = 0;+*stringptr = yield;+*sizeptr = size;+return 0;+}++++/*************************************************+* Free memory obtained by get_substring *+*************************************************/++/*+Argument: the result of a previous pcre2_substring_get_byxxx()+Returns: nothing+*/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_substring_free(PCRE2_UCHAR *string)+{+if (string != NULL)+ {+ pcre2_memctl *memctl = (pcre2_memctl *)((char *)string - sizeof(pcre2_memctl));+ memctl->free(memctl, memctl->memory_data);+ }+}++++/*************************************************+* Get length of a named substring *+*************************************************/++/* This function returns the length of a named captured substring. If the regex+permits duplicate names, the first substring that is set is chosen.++Arguments:+ match_data pointer to match data+ stringname the name of the required substring+ sizeptr where to put the length++Returns: 0 if successful, else a negative error number+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substring_length_byname(pcre2_match_data *match_data,+ PCRE2_SPTR stringname, PCRE2_SIZE *sizeptr)+{+PCRE2_SPTR first, last, entry;+int failrc, entrysize;+if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)+ return PCRE2_ERROR_DFA_UFUNC;+entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,+ &first, &last);+if (entrysize < 0) return entrysize;+failrc = PCRE2_ERROR_UNAVAILABLE;+for (entry = first; entry <= last; entry += entrysize)+ {+ uint32_t n = GET2(entry, 0);+ if (n < match_data->oveccount)+ {+ if (match_data->ovector[n*2] != PCRE2_UNSET)+ return pcre2_substring_length_bynumber(match_data, n, sizeptr);+ failrc = PCRE2_ERROR_UNSET;+ }+ }+return failrc;+}++++/*************************************************+* Get length of a numbered substring *+*************************************************/++/* This function returns the length of a captured substring. If the start is+beyond the end (which can happen when \K is used in an assertion), it sets the+length to zero.++Arguments:+ match_data pointer to match data+ stringnumber the number of the required substring+ sizeptr where to put the length, if not NULL++Returns: if successful: 0+ if not successful, a negative error code:+ PCRE2_ERROR_NOSUBSTRING: no such substring+ PCRE2_ERROR_UNAVAILABLE: ovector is too small+ PCRE2_ERROR_UNSET: substring is not set+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substring_length_bynumber(pcre2_match_data *match_data,+ uint32_t stringnumber, PCRE2_SIZE *sizeptr)+{+PCRE2_SIZE left, right;+int count = match_data->rc;+if (count == PCRE2_ERROR_PARTIAL)+ {+ if (stringnumber > 0) return PCRE2_ERROR_PARTIAL;+ count = 0;+ }+else if (count < 0) return count; /* Match failed */++if (match_data->matchedby != PCRE2_MATCHEDBY_DFA_INTERPRETER)+ {+ if (stringnumber > match_data->code->top_bracket)+ return PCRE2_ERROR_NOSUBSTRING;+ if (stringnumber >= match_data->oveccount)+ return PCRE2_ERROR_UNAVAILABLE;+ if (match_data->ovector[stringnumber*2] == PCRE2_UNSET)+ return PCRE2_ERROR_UNSET;+ }+else /* Matched using pcre2_dfa_match() */+ {+ if (stringnumber >= match_data->oveccount) return PCRE2_ERROR_UNAVAILABLE;+ if (count != 0 && stringnumber >= (uint32_t)count) return PCRE2_ERROR_UNSET;+ }++left = match_data->ovector[stringnumber*2];+right = match_data->ovector[stringnumber*2+1];+if (sizeptr != NULL) *sizeptr = (left > right)? 0 : right - left;+return 0;+}++++/*************************************************+* Extract all captured strings to new memory *+*************************************************/++/* This function gets one chunk of memory and builds a list of pointers and all+the captured substrings in it. A NULL pointer is put on the end of the list.+The substrings are zero-terminated, but also, if the final argument is+non-NULL, a list of lengths is also returned. This allows binary data to be+handled.++Arguments:+ match_data points to the match data+ listptr set to point to the list of pointers+ lengthsptr set to point to the list of lengths (may be NULL)++Returns: if successful: 0+ if not successful, a negative error code:+ PCRE2_ERROR_NOMEMORY: failed to get memory,+ or a match failure code+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substring_list_get(pcre2_match_data *match_data, PCRE2_UCHAR ***listptr,+ PCRE2_SIZE **lengthsptr)+{+int i, count, count2;+PCRE2_SIZE size;+PCRE2_SIZE *lensp;+pcre2_memctl *memp;+PCRE2_UCHAR **listp;+PCRE2_UCHAR *sp;+PCRE2_SIZE *ovector;++if ((count = match_data->rc) < 0) return count; /* Match failed */+if (count == 0) count = match_data->oveccount; /* Ovector too small */++count2 = 2*count;+ovector = match_data->ovector;+size = sizeof(pcre2_memctl) + sizeof(PCRE2_UCHAR *); /* For final NULL */+if (lengthsptr != NULL) size += sizeof(PCRE2_SIZE) * count; /* For lengths */++for (i = 0; i < count2; i += 2)+ {+ size += sizeof(PCRE2_UCHAR *) + CU2BYTES(1);+ if (ovector[i+1] > ovector[i]) size += CU2BYTES(ovector[i+1] - ovector[i]);+ }++memp = PRIV(memctl_malloc)(size, (pcre2_memctl *)match_data);+if (memp == NULL) return PCRE2_ERROR_NOMEMORY;++*listptr = listp = (PCRE2_UCHAR **)((char *)memp + sizeof(pcre2_memctl));+lensp = (PCRE2_SIZE *)((char *)listp + sizeof(PCRE2_UCHAR *) * (count + 1));++if (lengthsptr == NULL)+ {+ sp = (PCRE2_UCHAR *)lensp;+ lensp = NULL;+ }+else+ {+ *lengthsptr = lensp;+ sp = (PCRE2_UCHAR *)((char *)lensp + sizeof(PCRE2_SIZE) * count);+ }++for (i = 0; i < count2; i += 2)+ {+ size = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0;++ /* Size == 0 includes the case when the capture is unset. Avoid adding+ PCRE2_UNSET to match_data->subject because it overflows, even though with+ zero size calling memcpy() is harmless. */++ if (size != 0) memcpy(sp, match_data->subject + ovector[i], CU2BYTES(size));+ *listp++ = sp;+ if (lensp != NULL) *lensp++ = size;+ sp += size;+ *sp++ = 0;+ }++*listp = NULL;+return 0;+}++++/*************************************************+* Free memory obtained by substring_list_get *+*************************************************/++/*+Argument: the result of a previous pcre2_substring_list_get()+Returns: nothing+*/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_substring_list_free(PCRE2_SPTR *list)+{+if (list != NULL)+ {+ pcre2_memctl *memctl = (pcre2_memctl *)((char *)list - sizeof(pcre2_memctl));+ memctl->free(memctl, memctl->memory_data);+ }+}++++/*************************************************+* Find (multiple) entries for named string *+*************************************************/++/* This function scans the nametable for a given name, using binary chop. It+returns either two pointers to the entries in the table, or, if no pointers are+given, the number of a unique group with the given name. If duplicate names are+permitted, and the name is not unique, an error is generated.++Arguments:+ code the compiled regex+ stringname the name whose entries required+ firstptr where to put the pointer to the first entry+ lastptr where to put the pointer to the last entry++Returns: PCRE2_ERROR_NOSUBSTRING if the name is not found+ otherwise, if firstptr and lastptr are NULL:+ a group number for a unique substring+ else PCRE2_ERROR_NOUNIQUESUBSTRING+ otherwise:+ the length of each entry, having set firstptr and lastptr+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substring_nametable_scan(const pcre2_code *code, PCRE2_SPTR stringname,+ PCRE2_SPTR *firstptr, PCRE2_SPTR *lastptr)+{+uint16_t bot = 0;+uint16_t top = code->name_count;+uint16_t entrysize = code->name_entry_size;+PCRE2_SPTR nametable = (PCRE2_SPTR)((char *)code + sizeof(pcre2_real_code));++while (top > bot)+ {+ uint16_t mid = (top + bot) / 2;+ PCRE2_SPTR entry = nametable + entrysize*mid;+ int c = PRIV(strcmp)(stringname, entry + IMM2_SIZE);+ if (c == 0)+ {+ PCRE2_SPTR first;+ PCRE2_SPTR last;+ PCRE2_SPTR lastentry;+ lastentry = nametable + entrysize * (code->name_count - 1);+ first = last = entry;+ while (first > nametable)+ {+ if (PRIV(strcmp)(stringname, (first - entrysize + IMM2_SIZE)) != 0) break;+ first -= entrysize;+ }+ while (last < lastentry)+ {+ if (PRIV(strcmp)(stringname, (last + entrysize + IMM2_SIZE)) != 0) break;+ last += entrysize;+ }+ if (firstptr == NULL) return (first == last)?+ (int)GET2(entry, 0) : PCRE2_ERROR_NOUNIQUESUBSTRING;+ *firstptr = first;+ *lastptr = last;+ return entrysize;+ }+ if (c > 0) bot = mid + 1; else top = mid;+ }++return PCRE2_ERROR_NOSUBSTRING;+}+++/*************************************************+* Find number for named string *+*************************************************/++/* This function is a convenience wrapper for pcre2_substring_nametable_scan()+when it is known that names are unique. If there are duplicate names, it is not+defined which number is returned.++Arguments:+ code the compiled regex+ stringname the name whose number is required++Returns: the number of the named parenthesis, or a negative number+ PCRE2_ERROR_NOSUBSTRING if not found+ PCRE2_ERROR_NOUNIQUESUBSTRING if not unique+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substring_number_from_name(const pcre2_code *code,+ PCRE2_SPTR stringname)+{+return pcre2_substring_nametable_scan(code, stringname, NULL, NULL);+}++/* End of pcre2_substring.c */
+ src/c/pcre2/src/pcre2_tables.c view
@@ -0,0 +1,854 @@+/*************************************************+* 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) 2016-2019 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.+-----------------------------------------------------------------------------+*/++/* This module contains some fixed tables that are used by more than one of the+PCRE2 code modules. The tables are also #included by the pcre2test program,+which uses macros to change their names from _pcre2_xxx to xxxx, thereby+avoiding name clashes with the library. In this case, PCRE2_PCRE2TEST is+defined. */++#ifndef PCRE2_PCRE2TEST /* We're compiling the library */+#ifdef HAVE_CONFIG_H+#include "config.h"+#endif+#include "pcre2_internal.h"+#endif /* PCRE2_PCRE2TEST */+++/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that+the definition is next to the definition of the opcodes in pcre2_internal.h.+This is mode-dependent, so is skipped when this file is included by pcre2test. */++#ifndef PCRE2_PCRE2TEST+const uint8_t PRIV(OP_lengths)[] = { OP_LENGTHS };+#endif++/* Tables of horizontal and vertical whitespace characters, suitable for+adding to classes. */++const uint32_t PRIV(hspace_list)[] = { HSPACE_LIST };+const uint32_t PRIV(vspace_list)[] = { VSPACE_LIST };++/* These tables are the pairs of delimiters that are valid for callout string+arguments. For each starting delimiter there must be a matching ending+delimiter, which in fact is different only for bracket-like delimiters. */++const uint32_t PRIV(callout_start_delims)[] = {+ CHAR_GRAVE_ACCENT, CHAR_APOSTROPHE, CHAR_QUOTATION_MARK,+ CHAR_CIRCUMFLEX_ACCENT, CHAR_PERCENT_SIGN, CHAR_NUMBER_SIGN,+ CHAR_DOLLAR_SIGN, CHAR_LEFT_CURLY_BRACKET, 0 };++const uint32_t PRIV(callout_end_delims[]) = {+ CHAR_GRAVE_ACCENT, CHAR_APOSTROPHE, CHAR_QUOTATION_MARK,+ CHAR_CIRCUMFLEX_ACCENT, CHAR_PERCENT_SIGN, CHAR_NUMBER_SIGN,+ CHAR_DOLLAR_SIGN, CHAR_RIGHT_CURLY_BRACKET, 0 };+++/*************************************************+* Tables for UTF-8 support *+*************************************************/++/* These tables are required by pcre2test in 16- or 32-bit mode, as well+as for the library in 8-bit mode, because pcre2test uses UTF-8 internally for+handling wide characters. */++#if defined PCRE2_PCRE2TEST || \+ (defined SUPPORT_UNICODE && \+ defined PCRE2_CODE_UNIT_WIDTH && \+ PCRE2_CODE_UNIT_WIDTH == 8)++/* These are the breakpoints for different numbers of bytes in a UTF-8+character. */++const int PRIV(utf8_table1)[] =+ { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};++const int PRIV(utf8_table1_size) = sizeof(PRIV(utf8_table1)) / sizeof(int);++/* These are the indicator bits and the mask for the data bits to set in the+first byte of a character, indexed by the number of additional bytes. */++const int PRIV(utf8_table2)[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};+const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};++/* Table of the number of extra bytes, indexed by the first byte masked with+0x3f. The highest number for a valid UTF-8 first byte is in fact 0x3d. */++const uint8_t PRIV(utf8_table4)[] = {+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,+ 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };++#endif /* UTF-8 support needed */+++#ifdef SUPPORT_UNICODE++/* Table to translate from particular type value to the general value. */++const uint32_t PRIV(ucp_gentype)[] = {+ ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */+ ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */+ ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */+ ucp_N, ucp_N, ucp_N, /* Nd, Nl, No */+ ucp_P, ucp_P, ucp_P, ucp_P, ucp_P, /* Pc, Pd, Pe, Pf, Pi */+ ucp_P, ucp_P, /* Ps, Po */+ ucp_S, ucp_S, ucp_S, ucp_S, /* Sc, Sk, Sm, So */+ ucp_Z, ucp_Z, ucp_Z /* Zl, Zp, Zs */+};++/* This table encodes the rules for finding the end of an extended grapheme+cluster. Every code point has a grapheme break property which is one of the+ucp_gbXX values defined in pcre2_ucp.h. These changed between Unicode versions+10 and 11. The 2-dimensional table is indexed by the properties of two adjacent+code points. The left property selects a word from the table, and the right+property selects a bit from that word like this:++ PRIV(ucp_gbtable)[left-property] & (1u << right-property)++The value is non-zero if a grapheme break is NOT permitted between the relevant+two code points. The breaking rules are as follows:++1. Break at the start and end of text (pretty obviously).++2. Do not break between a CR and LF; otherwise, break before and after+ controls.++3. Do not break Hangul syllable sequences, the rules for which are:++ L may be followed by L, V, LV or LVT+ LV or V may be followed by V or T+ LVT or T may be followed by T++4. Do not break before extending characters or zero-width-joiner (ZWJ).++The following rules are only for extended grapheme clusters (but that's what we+are implementing).++5. Do not break before SpacingMarks.++6. Do not break after Prepend characters.++7. Do not break within emoji modifier sequences or emoji zwj sequences. That+ is, do not break between characters with the Extended_Pictographic property.+ Extend and ZWJ characters are allowed between the characters; this cannot be+ represented in this table, the code has to deal with it.++8. Do not break within emoji flag sequences. That is, do not break between+ regional indicator (RI) symbols if there are an odd number of RI characters+ before the break point. This table encodes "join RI characters"; the code+ has to deal with checking for previous adjoining RIs.++9. Otherwise, break everywhere.+*/++#define ESZ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbZWJ)++const uint32_t PRIV(ucp_gbtable)[] = {+ (1u<<ucp_gbLF), /* 0 CR */+ 0, /* 1 LF */+ 0, /* 2 Control */+ ESZ, /* 3 Extend */+ ESZ|(1u<<ucp_gbPrepend)| /* 4 Prepend */+ (1u<<ucp_gbL)|(1u<<ucp_gbV)|(1u<<ucp_gbT)|+ (1u<<ucp_gbLV)|(1u<<ucp_gbLVT)|(1u<<ucp_gbOther)|+ (1u<<ucp_gbRegionalIndicator),+ ESZ, /* 5 SpacingMark */+ ESZ|(1u<<ucp_gbL)|(1u<<ucp_gbV)|(1u<<ucp_gbLV)| /* 6 L */+ (1u<<ucp_gbLVT),+ ESZ|(1u<<ucp_gbV)|(1u<<ucp_gbT), /* 7 V */+ ESZ|(1u<<ucp_gbT), /* 8 T */+ ESZ|(1u<<ucp_gbV)|(1u<<ucp_gbT), /* 9 LV */+ ESZ|(1u<<ucp_gbT), /* 10 LVT */+ (1u<<ucp_gbRegionalIndicator), /* 11 RegionalIndicator */+ ESZ, /* 12 Other */+ ESZ, /* 13 ZWJ */+ ESZ|(1u<<ucp_gbExtended_Pictographic) /* 14 Extended Pictographic */+};++#undef ESZ++#ifdef SUPPORT_JIT+/* This table reverses PRIV(ucp_gentype). We can save the cost+of a memory load. */++const int PRIV(ucp_typerange)[] = {+ ucp_Cc, ucp_Cs,+ ucp_Ll, ucp_Lu,+ ucp_Mc, ucp_Mn,+ ucp_Nd, ucp_No,+ ucp_Pc, ucp_Ps,+ ucp_Sc, ucp_So,+ ucp_Zl, ucp_Zs,+};+#endif /* SUPPORT_JIT */++/* The PRIV(utt)[] table below translates Unicode property names into type and+code values. It is searched by binary chop, so must be in collating sequence of+name. Originally, the table contained pointers to the name strings in the first+field of each entry. However, that leads to a large number of relocations when+a shared library is dynamically loaded. A significant reduction is made by+putting all the names into a single, large string and then using offsets in the+table itself. Maintenance is more error-prone, but frequent changes to this+data are unlikely.++July 2008: There is now a script called maint/GenerateUtt.py that can be used+to generate this data automatically instead of maintaining it by hand.++The script was updated in March 2009 to generate a new EBCDIC-compliant+version. Like all other character and string literals that are compared against+the regular expression pattern, we must use STR_ macros instead of literal+strings to make sure that UTF-8 support works on EBCDIC platforms. */++#define STRING_Adlam0 STR_A STR_d STR_l STR_a STR_m "\0"+#define STRING_Ahom0 STR_A STR_h STR_o STR_m "\0"+#define STRING_Anatolian_Hieroglyphs0 STR_A STR_n STR_a STR_t STR_o STR_l STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"+#define STRING_Any0 STR_A STR_n STR_y "\0"+#define STRING_Arabic0 STR_A STR_r STR_a STR_b STR_i STR_c "\0"+#define STRING_Armenian0 STR_A STR_r STR_m STR_e STR_n STR_i STR_a STR_n "\0"+#define STRING_Avestan0 STR_A STR_v STR_e STR_s STR_t STR_a STR_n "\0"+#define STRING_Balinese0 STR_B STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0"+#define STRING_Bamum0 STR_B STR_a STR_m STR_u STR_m "\0"+#define STRING_Bassa_Vah0 STR_B STR_a STR_s STR_s STR_a STR_UNDERSCORE STR_V STR_a STR_h "\0"+#define STRING_Batak0 STR_B STR_a STR_t STR_a STR_k "\0"+#define STRING_Bengali0 STR_B STR_e STR_n STR_g STR_a STR_l STR_i "\0"+#define STRING_Bhaiksuki0 STR_B STR_h STR_a STR_i STR_k STR_s STR_u STR_k STR_i "\0"+#define STRING_Bopomofo0 STR_B STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0"+#define STRING_Brahmi0 STR_B STR_r STR_a STR_h STR_m STR_i "\0"+#define STRING_Braille0 STR_B STR_r STR_a STR_i STR_l STR_l STR_e "\0"+#define STRING_Buginese0 STR_B STR_u STR_g STR_i STR_n STR_e STR_s STR_e "\0"+#define STRING_Buhid0 STR_B STR_u STR_h STR_i STR_d "\0"+#define STRING_C0 STR_C "\0"+#define STRING_Canadian_Aboriginal0 STR_C STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0"+#define STRING_Carian0 STR_C STR_a STR_r STR_i STR_a STR_n "\0"+#define STRING_Caucasian_Albanian0 STR_C STR_a STR_u STR_c STR_a STR_s STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_l STR_b STR_a STR_n STR_i STR_a STR_n "\0"+#define STRING_Cc0 STR_C STR_c "\0"+#define STRING_Cf0 STR_C STR_f "\0"+#define STRING_Chakma0 STR_C STR_h STR_a STR_k STR_m STR_a "\0"+#define STRING_Cham0 STR_C STR_h STR_a STR_m "\0"+#define STRING_Cherokee0 STR_C STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0"+#define STRING_Chorasmian0 STR_C STR_h STR_o STR_r STR_a STR_s STR_m STR_i STR_a STR_n "\0"+#define STRING_Cn0 STR_C STR_n "\0"+#define STRING_Co0 STR_C STR_o "\0"+#define STRING_Common0 STR_C STR_o STR_m STR_m STR_o STR_n "\0"+#define STRING_Coptic0 STR_C STR_o STR_p STR_t STR_i STR_c "\0"+#define STRING_Cs0 STR_C STR_s "\0"+#define STRING_Cuneiform0 STR_C STR_u STR_n STR_e STR_i STR_f STR_o STR_r STR_m "\0"+#define STRING_Cypriot0 STR_C STR_y STR_p STR_r STR_i STR_o STR_t "\0"+#define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0"+#define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0"+#define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0"+#define STRING_Dives_Akuru0 STR_D STR_i STR_v STR_e STR_s STR_UNDERSCORE STR_A STR_k STR_u STR_r STR_u "\0"+#define STRING_Dogra0 STR_D STR_o STR_g STR_r STR_a "\0"+#define STRING_Duployan0 STR_D STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0"+#define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"+#define STRING_Elbasan0 STR_E STR_l STR_b STR_a STR_s STR_a STR_n "\0"+#define STRING_Elymaic0 STR_E STR_l STR_y STR_m STR_a STR_i STR_c "\0"+#define STRING_Ethiopic0 STR_E STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0"+#define STRING_Georgian0 STR_G STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0"+#define STRING_Glagolitic0 STR_G STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0"+#define STRING_Gothic0 STR_G STR_o STR_t STR_h STR_i STR_c "\0"+#define STRING_Grantha0 STR_G STR_r STR_a STR_n STR_t STR_h STR_a "\0"+#define STRING_Greek0 STR_G STR_r STR_e STR_e STR_k "\0"+#define STRING_Gujarati0 STR_G STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0"+#define STRING_Gunjala_Gondi0 STR_G STR_u STR_n STR_j STR_a STR_l STR_a STR_UNDERSCORE STR_G STR_o STR_n STR_d STR_i "\0"+#define STRING_Gurmukhi0 STR_G STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0"+#define STRING_Han0 STR_H STR_a STR_n "\0"+#define STRING_Hangul0 STR_H STR_a STR_n STR_g STR_u STR_l "\0"+#define STRING_Hanifi_Rohingya0 STR_H STR_a STR_n STR_i STR_f STR_i STR_UNDERSCORE STR_R STR_o STR_h STR_i STR_n STR_g STR_y STR_a "\0"+#define STRING_Hanunoo0 STR_H STR_a STR_n STR_u STR_n STR_o STR_o "\0"+#define STRING_Hatran0 STR_H STR_a STR_t STR_r STR_a STR_n "\0"+#define STRING_Hebrew0 STR_H STR_e STR_b STR_r STR_e STR_w "\0"+#define STRING_Hiragana0 STR_H STR_i STR_r STR_a STR_g STR_a STR_n STR_a "\0"+#define STRING_Imperial_Aramaic0 STR_I STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_UNDERSCORE STR_A STR_r STR_a STR_m STR_a STR_i STR_c "\0"+#define STRING_Inherited0 STR_I STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0"+#define STRING_Inscriptional_Pahlavi0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_h STR_l STR_a STR_v STR_i "\0"+#define STRING_Inscriptional_Parthian0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0"+#define STRING_Javanese0 STR_J STR_a STR_v STR_a STR_n STR_e STR_s STR_e "\0"+#define STRING_Kaithi0 STR_K STR_a STR_i STR_t STR_h STR_i "\0"+#define STRING_Kannada0 STR_K STR_a STR_n STR_n STR_a STR_d STR_a "\0"+#define STRING_Katakana0 STR_K STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0"+#define STRING_Kayah_Li0 STR_K STR_a STR_y STR_a STR_h STR_UNDERSCORE STR_L STR_i "\0"+#define STRING_Kharoshthi0 STR_K STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0"+#define STRING_Khitan_Small_Script0 STR_K STR_h STR_i STR_t STR_a STR_n STR_UNDERSCORE STR_S STR_m STR_a STR_l STR_l STR_UNDERSCORE STR_S STR_c STR_r STR_i STR_p STR_t "\0"+#define STRING_Khmer0 STR_K STR_h STR_m STR_e STR_r "\0"+#define STRING_Khojki0 STR_K STR_h STR_o STR_j STR_k STR_i "\0"+#define STRING_Khudawadi0 STR_K STR_h STR_u STR_d STR_a STR_w STR_a STR_d STR_i "\0"+#define STRING_L0 STR_L "\0"+#define STRING_L_AMPERSAND0 STR_L STR_AMPERSAND "\0"+#define STRING_Lao0 STR_L STR_a STR_o "\0"+#define STRING_Latin0 STR_L STR_a STR_t STR_i STR_n "\0"+#define STRING_Lepcha0 STR_L STR_e STR_p STR_c STR_h STR_a "\0"+#define STRING_Limbu0 STR_L STR_i STR_m STR_b STR_u "\0"+#define STRING_Linear_A0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_A "\0"+#define STRING_Linear_B0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_B "\0"+#define STRING_Lisu0 STR_L STR_i STR_s STR_u "\0"+#define STRING_Ll0 STR_L STR_l "\0"+#define STRING_Lm0 STR_L STR_m "\0"+#define STRING_Lo0 STR_L STR_o "\0"+#define STRING_Lt0 STR_L STR_t "\0"+#define STRING_Lu0 STR_L STR_u "\0"+#define STRING_Lycian0 STR_L STR_y STR_c STR_i STR_a STR_n "\0"+#define STRING_Lydian0 STR_L STR_y STR_d STR_i STR_a STR_n "\0"+#define STRING_M0 STR_M "\0"+#define STRING_Mahajani0 STR_M STR_a STR_h STR_a STR_j STR_a STR_n STR_i "\0"+#define STRING_Makasar0 STR_M STR_a STR_k STR_a STR_s STR_a STR_r "\0"+#define STRING_Malayalam0 STR_M STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0"+#define STRING_Mandaic0 STR_M STR_a STR_n STR_d STR_a STR_i STR_c "\0"+#define STRING_Manichaean0 STR_M STR_a STR_n STR_i STR_c STR_h STR_a STR_e STR_a STR_n "\0"+#define STRING_Marchen0 STR_M STR_a STR_r STR_c STR_h STR_e STR_n "\0"+#define STRING_Masaram_Gondi0 STR_M STR_a STR_s STR_a STR_r STR_a STR_m STR_UNDERSCORE STR_G STR_o STR_n STR_d STR_i "\0"+#define STRING_Mc0 STR_M STR_c "\0"+#define STRING_Me0 STR_M STR_e "\0"+#define STRING_Medefaidrin0 STR_M STR_e STR_d STR_e STR_f STR_a STR_i STR_d STR_r STR_i STR_n "\0"+#define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0"+#define STRING_Mende_Kikakui0 STR_M STR_e STR_n STR_d STR_e STR_UNDERSCORE STR_K STR_i STR_k STR_a STR_k STR_u STR_i "\0"+#define STRING_Meroitic_Cursive0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_C STR_u STR_r STR_s STR_i STR_v STR_e "\0"+#define STRING_Meroitic_Hieroglyphs0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"+#define STRING_Miao0 STR_M STR_i STR_a STR_o "\0"+#define STRING_Mn0 STR_M STR_n "\0"+#define STRING_Modi0 STR_M STR_o STR_d STR_i "\0"+#define STRING_Mongolian0 STR_M STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"+#define STRING_Mro0 STR_M STR_r STR_o "\0"+#define STRING_Multani0 STR_M STR_u STR_l STR_t STR_a STR_n STR_i "\0"+#define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0"+#define STRING_N0 STR_N "\0"+#define STRING_Nabataean0 STR_N STR_a STR_b STR_a STR_t STR_a STR_e STR_a STR_n "\0"+#define STRING_Nandinagari0 STR_N STR_a STR_n STR_d STR_i STR_n STR_a STR_g STR_a STR_r STR_i "\0"+#define STRING_Nd0 STR_N STR_d "\0"+#define STRING_New_Tai_Lue0 STR_N STR_e STR_w STR_UNDERSCORE STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_u STR_e "\0"+#define STRING_Newa0 STR_N STR_e STR_w STR_a "\0"+#define STRING_Nko0 STR_N STR_k STR_o "\0"+#define STRING_Nl0 STR_N STR_l "\0"+#define STRING_No0 STR_N STR_o "\0"+#define STRING_Nushu0 STR_N STR_u STR_s STR_h STR_u "\0"+#define STRING_Nyiakeng_Puachue_Hmong0 STR_N STR_y STR_i STR_a STR_k STR_e STR_n STR_g STR_UNDERSCORE STR_P STR_u STR_a STR_c STR_h STR_u STR_e STR_UNDERSCORE STR_H STR_m STR_o STR_n STR_g "\0"+#define STRING_Ogham0 STR_O STR_g STR_h STR_a STR_m "\0"+#define STRING_Ol_Chiki0 STR_O STR_l STR_UNDERSCORE STR_C STR_h STR_i STR_k STR_i "\0"+#define STRING_Old_Hungarian0 STR_O STR_l STR_d STR_UNDERSCORE STR_H STR_u STR_n STR_g STR_a STR_r STR_i STR_a STR_n "\0"+#define STRING_Old_Italic0 STR_O STR_l STR_d STR_UNDERSCORE STR_I STR_t STR_a STR_l STR_i STR_c "\0"+#define STRING_Old_North_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_N STR_o STR_r STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"+#define STRING_Old_Permic0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_m STR_i STR_c "\0"+#define STRING_Old_Persian0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_s STR_i STR_a STR_n "\0"+#define STRING_Old_Sogdian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_g STR_d STR_i STR_a STR_n "\0"+#define STRING_Old_South_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_u STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"+#define STRING_Old_Turkic0 STR_O STR_l STR_d STR_UNDERSCORE STR_T STR_u STR_r STR_k STR_i STR_c "\0"+#define STRING_Oriya0 STR_O STR_r STR_i STR_y STR_a "\0"+#define STRING_Osage0 STR_O STR_s STR_a STR_g STR_e "\0"+#define STRING_Osmanya0 STR_O STR_s STR_m STR_a STR_n STR_y STR_a "\0"+#define STRING_P0 STR_P "\0"+#define STRING_Pahawh_Hmong0 STR_P STR_a STR_h STR_a STR_w STR_h STR_UNDERSCORE STR_H STR_m STR_o STR_n STR_g "\0"+#define STRING_Palmyrene0 STR_P STR_a STR_l STR_m STR_y STR_r STR_e STR_n STR_e "\0"+#define STRING_Pau_Cin_Hau0 STR_P STR_a STR_u STR_UNDERSCORE STR_C STR_i STR_n STR_UNDERSCORE STR_H STR_a STR_u "\0"+#define STRING_Pc0 STR_P STR_c "\0"+#define STRING_Pd0 STR_P STR_d "\0"+#define STRING_Pe0 STR_P STR_e "\0"+#define STRING_Pf0 STR_P STR_f "\0"+#define STRING_Phags_Pa0 STR_P STR_h STR_a STR_g STR_s STR_UNDERSCORE STR_P STR_a "\0"+#define STRING_Phoenician0 STR_P STR_h STR_o STR_e STR_n STR_i STR_c STR_i STR_a STR_n "\0"+#define STRING_Pi0 STR_P STR_i "\0"+#define STRING_Po0 STR_P STR_o "\0"+#define STRING_Ps0 STR_P STR_s "\0"+#define STRING_Psalter_Pahlavi0 STR_P STR_s STR_a STR_l STR_t STR_e STR_r STR_UNDERSCORE STR_P STR_a STR_h STR_l STR_a STR_v STR_i "\0"+#define STRING_Rejang0 STR_R STR_e STR_j STR_a STR_n STR_g "\0"+#define STRING_Runic0 STR_R STR_u STR_n STR_i STR_c "\0"+#define STRING_S0 STR_S "\0"+#define STRING_Samaritan0 STR_S STR_a STR_m STR_a STR_r STR_i STR_t STR_a STR_n "\0"+#define STRING_Saurashtra0 STR_S STR_a STR_u STR_r STR_a STR_s STR_h STR_t STR_r STR_a "\0"+#define STRING_Sc0 STR_S STR_c "\0"+#define STRING_Sharada0 STR_S STR_h STR_a STR_r STR_a STR_d STR_a "\0"+#define STRING_Shavian0 STR_S STR_h STR_a STR_v STR_i STR_a STR_n "\0"+#define STRING_Siddham0 STR_S STR_i STR_d STR_d STR_h STR_a STR_m "\0"+#define STRING_SignWriting0 STR_S STR_i STR_g STR_n STR_W STR_r STR_i STR_t STR_i STR_n STR_g "\0"+#define STRING_Sinhala0 STR_S STR_i STR_n STR_h STR_a STR_l STR_a "\0"+#define STRING_Sk0 STR_S STR_k "\0"+#define STRING_Sm0 STR_S STR_m "\0"+#define STRING_So0 STR_S STR_o "\0"+#define STRING_Sogdian0 STR_S STR_o STR_g STR_d STR_i STR_a STR_n "\0"+#define STRING_Sora_Sompeng0 STR_S STR_o STR_r STR_a STR_UNDERSCORE STR_S STR_o STR_m STR_p STR_e STR_n STR_g "\0"+#define STRING_Soyombo0 STR_S STR_o STR_y STR_o STR_m STR_b STR_o "\0"+#define STRING_Sundanese0 STR_S STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0"+#define STRING_Syloti_Nagri0 STR_S STR_y STR_l STR_o STR_t STR_i STR_UNDERSCORE STR_N STR_a STR_g STR_r STR_i "\0"+#define STRING_Syriac0 STR_S STR_y STR_r STR_i STR_a STR_c "\0"+#define STRING_Tagalog0 STR_T STR_a STR_g STR_a STR_l STR_o STR_g "\0"+#define STRING_Tagbanwa0 STR_T STR_a STR_g STR_b STR_a STR_n STR_w STR_a "\0"+#define STRING_Tai_Le0 STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_e "\0"+#define STRING_Tai_Tham0 STR_T STR_a STR_i STR_UNDERSCORE STR_T STR_h STR_a STR_m "\0"+#define STRING_Tai_Viet0 STR_T STR_a STR_i STR_UNDERSCORE STR_V STR_i STR_e STR_t "\0"+#define STRING_Takri0 STR_T STR_a STR_k STR_r STR_i "\0"+#define STRING_Tamil0 STR_T STR_a STR_m STR_i STR_l "\0"+#define STRING_Tangut0 STR_T STR_a STR_n STR_g STR_u STR_t "\0"+#define STRING_Telugu0 STR_T STR_e STR_l STR_u STR_g STR_u "\0"+#define STRING_Thaana0 STR_T STR_h STR_a STR_a STR_n STR_a "\0"+#define STRING_Thai0 STR_T STR_h STR_a STR_i "\0"+#define STRING_Tibetan0 STR_T STR_i STR_b STR_e STR_t STR_a STR_n "\0"+#define STRING_Tifinagh0 STR_T STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0"+#define STRING_Tirhuta0 STR_T STR_i STR_r STR_h STR_u STR_t STR_a "\0"+#define STRING_Ugaritic0 STR_U STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"+#define STRING_Unknown0 STR_U STR_n STR_k STR_n STR_o STR_w STR_n "\0"+#define STRING_Vai0 STR_V STR_a STR_i "\0"+#define STRING_Wancho0 STR_W STR_a STR_n STR_c STR_h STR_o "\0"+#define STRING_Warang_Citi0 STR_W STR_a STR_r STR_a STR_n STR_g STR_UNDERSCORE STR_C STR_i STR_t STR_i "\0"+#define STRING_Xan0 STR_X STR_a STR_n "\0"+#define STRING_Xps0 STR_X STR_p STR_s "\0"+#define STRING_Xsp0 STR_X STR_s STR_p "\0"+#define STRING_Xuc0 STR_X STR_u STR_c "\0"+#define STRING_Xwd0 STR_X STR_w STR_d "\0"+#define STRING_Yezidi0 STR_Y STR_e STR_z STR_i STR_d STR_i "\0"+#define STRING_Yi0 STR_Y STR_i "\0"+#define STRING_Z0 STR_Z "\0"+#define STRING_Zanabazar_Square0 STR_Z STR_a STR_n STR_a STR_b STR_a STR_z STR_a STR_r STR_UNDERSCORE STR_S STR_q STR_u STR_a STR_r STR_e "\0"+#define STRING_Zl0 STR_Z STR_l "\0"+#define STRING_Zp0 STR_Z STR_p "\0"+#define STRING_Zs0 STR_Z STR_s "\0"++const char PRIV(utt_names)[] =+ STRING_Adlam0+ STRING_Ahom0+ STRING_Anatolian_Hieroglyphs0+ STRING_Any0+ STRING_Arabic0+ STRING_Armenian0+ STRING_Avestan0+ STRING_Balinese0+ STRING_Bamum0+ STRING_Bassa_Vah0+ STRING_Batak0+ STRING_Bengali0+ STRING_Bhaiksuki0+ STRING_Bopomofo0+ STRING_Brahmi0+ STRING_Braille0+ STRING_Buginese0+ STRING_Buhid0+ STRING_C0+ STRING_Canadian_Aboriginal0+ STRING_Carian0+ STRING_Caucasian_Albanian0+ STRING_Cc0+ STRING_Cf0+ STRING_Chakma0+ STRING_Cham0+ STRING_Cherokee0+ STRING_Chorasmian0+ STRING_Cn0+ STRING_Co0+ STRING_Common0+ STRING_Coptic0+ STRING_Cs0+ STRING_Cuneiform0+ STRING_Cypriot0+ STRING_Cyrillic0+ STRING_Deseret0+ STRING_Devanagari0+ STRING_Dives_Akuru0+ STRING_Dogra0+ STRING_Duployan0+ STRING_Egyptian_Hieroglyphs0+ STRING_Elbasan0+ STRING_Elymaic0+ STRING_Ethiopic0+ STRING_Georgian0+ STRING_Glagolitic0+ STRING_Gothic0+ STRING_Grantha0+ STRING_Greek0+ STRING_Gujarati0+ STRING_Gunjala_Gondi0+ STRING_Gurmukhi0+ STRING_Han0+ STRING_Hangul0+ STRING_Hanifi_Rohingya0+ STRING_Hanunoo0+ STRING_Hatran0+ STRING_Hebrew0+ STRING_Hiragana0+ STRING_Imperial_Aramaic0+ STRING_Inherited0+ STRING_Inscriptional_Pahlavi0+ STRING_Inscriptional_Parthian0+ STRING_Javanese0+ STRING_Kaithi0+ STRING_Kannada0+ STRING_Katakana0+ STRING_Kayah_Li0+ STRING_Kharoshthi0+ STRING_Khitan_Small_Script0+ STRING_Khmer0+ STRING_Khojki0+ STRING_Khudawadi0+ STRING_L0+ STRING_L_AMPERSAND0+ STRING_Lao0+ STRING_Latin0+ STRING_Lepcha0+ STRING_Limbu0+ STRING_Linear_A0+ STRING_Linear_B0+ STRING_Lisu0+ STRING_Ll0+ STRING_Lm0+ STRING_Lo0+ STRING_Lt0+ STRING_Lu0+ STRING_Lycian0+ STRING_Lydian0+ STRING_M0+ STRING_Mahajani0+ STRING_Makasar0+ STRING_Malayalam0+ STRING_Mandaic0+ STRING_Manichaean0+ STRING_Marchen0+ STRING_Masaram_Gondi0+ STRING_Mc0+ STRING_Me0+ STRING_Medefaidrin0+ STRING_Meetei_Mayek0+ STRING_Mende_Kikakui0+ STRING_Meroitic_Cursive0+ STRING_Meroitic_Hieroglyphs0+ STRING_Miao0+ STRING_Mn0+ STRING_Modi0+ STRING_Mongolian0+ STRING_Mro0+ STRING_Multani0+ STRING_Myanmar0+ STRING_N0+ STRING_Nabataean0+ STRING_Nandinagari0+ STRING_Nd0+ STRING_New_Tai_Lue0+ STRING_Newa0+ STRING_Nko0+ STRING_Nl0+ STRING_No0+ STRING_Nushu0+ STRING_Nyiakeng_Puachue_Hmong0+ STRING_Ogham0+ STRING_Ol_Chiki0+ STRING_Old_Hungarian0+ STRING_Old_Italic0+ STRING_Old_North_Arabian0+ STRING_Old_Permic0+ STRING_Old_Persian0+ STRING_Old_Sogdian0+ STRING_Old_South_Arabian0+ STRING_Old_Turkic0+ STRING_Oriya0+ STRING_Osage0+ STRING_Osmanya0+ STRING_P0+ STRING_Pahawh_Hmong0+ STRING_Palmyrene0+ STRING_Pau_Cin_Hau0+ STRING_Pc0+ STRING_Pd0+ STRING_Pe0+ STRING_Pf0+ STRING_Phags_Pa0+ STRING_Phoenician0+ STRING_Pi0+ STRING_Po0+ STRING_Ps0+ STRING_Psalter_Pahlavi0+ STRING_Rejang0+ STRING_Runic0+ STRING_S0+ STRING_Samaritan0+ STRING_Saurashtra0+ STRING_Sc0+ STRING_Sharada0+ STRING_Shavian0+ STRING_Siddham0+ STRING_SignWriting0+ STRING_Sinhala0+ STRING_Sk0+ STRING_Sm0+ STRING_So0+ STRING_Sogdian0+ STRING_Sora_Sompeng0+ STRING_Soyombo0+ STRING_Sundanese0+ STRING_Syloti_Nagri0+ STRING_Syriac0+ STRING_Tagalog0+ STRING_Tagbanwa0+ STRING_Tai_Le0+ STRING_Tai_Tham0+ STRING_Tai_Viet0+ STRING_Takri0+ STRING_Tamil0+ STRING_Tangut0+ STRING_Telugu0+ STRING_Thaana0+ STRING_Thai0+ STRING_Tibetan0+ STRING_Tifinagh0+ STRING_Tirhuta0+ STRING_Ugaritic0+ STRING_Unknown0+ STRING_Vai0+ STRING_Wancho0+ STRING_Warang_Citi0+ STRING_Xan0+ STRING_Xps0+ STRING_Xsp0+ STRING_Xuc0+ STRING_Xwd0+ STRING_Yezidi0+ STRING_Yi0+ STRING_Z0+ STRING_Zanabazar_Square0+ STRING_Zl0+ STRING_Zp0+ STRING_Zs0;++const ucp_type_table PRIV(utt)[] = {+ { 0, PT_SC, ucp_Adlam },+ { 6, PT_SC, ucp_Ahom },+ { 11, PT_SC, ucp_Anatolian_Hieroglyphs },+ { 33, PT_ANY, 0 },+ { 37, PT_SC, ucp_Arabic },+ { 44, PT_SC, ucp_Armenian },+ { 53, PT_SC, ucp_Avestan },+ { 61, PT_SC, ucp_Balinese },+ { 70, PT_SC, ucp_Bamum },+ { 76, PT_SC, ucp_Bassa_Vah },+ { 86, PT_SC, ucp_Batak },+ { 92, PT_SC, ucp_Bengali },+ { 100, PT_SC, ucp_Bhaiksuki },+ { 110, PT_SC, ucp_Bopomofo },+ { 119, PT_SC, ucp_Brahmi },+ { 126, PT_SC, ucp_Braille },+ { 134, PT_SC, ucp_Buginese },+ { 143, PT_SC, ucp_Buhid },+ { 149, PT_GC, ucp_C },+ { 151, PT_SC, ucp_Canadian_Aboriginal },+ { 171, PT_SC, ucp_Carian },+ { 178, PT_SC, ucp_Caucasian_Albanian },+ { 197, PT_PC, ucp_Cc },+ { 200, PT_PC, ucp_Cf },+ { 203, PT_SC, ucp_Chakma },+ { 210, PT_SC, ucp_Cham },+ { 215, PT_SC, ucp_Cherokee },+ { 224, PT_SC, ucp_Chorasmian },+ { 235, PT_PC, ucp_Cn },+ { 238, PT_PC, ucp_Co },+ { 241, PT_SC, ucp_Common },+ { 248, PT_SC, ucp_Coptic },+ { 255, PT_PC, ucp_Cs },+ { 258, PT_SC, ucp_Cuneiform },+ { 268, PT_SC, ucp_Cypriot },+ { 276, PT_SC, ucp_Cyrillic },+ { 285, PT_SC, ucp_Deseret },+ { 293, PT_SC, ucp_Devanagari },+ { 304, PT_SC, ucp_Dives_Akuru },+ { 316, PT_SC, ucp_Dogra },+ { 322, PT_SC, ucp_Duployan },+ { 331, PT_SC, ucp_Egyptian_Hieroglyphs },+ { 352, PT_SC, ucp_Elbasan },+ { 360, PT_SC, ucp_Elymaic },+ { 368, PT_SC, ucp_Ethiopic },+ { 377, PT_SC, ucp_Georgian },+ { 386, PT_SC, ucp_Glagolitic },+ { 397, PT_SC, ucp_Gothic },+ { 404, PT_SC, ucp_Grantha },+ { 412, PT_SC, ucp_Greek },+ { 418, PT_SC, ucp_Gujarati },+ { 427, PT_SC, ucp_Gunjala_Gondi },+ { 441, PT_SC, ucp_Gurmukhi },+ { 450, PT_SC, ucp_Han },+ { 454, PT_SC, ucp_Hangul },+ { 461, PT_SC, ucp_Hanifi_Rohingya },+ { 477, PT_SC, ucp_Hanunoo },+ { 485, PT_SC, ucp_Hatran },+ { 492, PT_SC, ucp_Hebrew },+ { 499, PT_SC, ucp_Hiragana },+ { 508, PT_SC, ucp_Imperial_Aramaic },+ { 525, PT_SC, ucp_Inherited },+ { 535, PT_SC, ucp_Inscriptional_Pahlavi },+ { 557, PT_SC, ucp_Inscriptional_Parthian },+ { 580, PT_SC, ucp_Javanese },+ { 589, PT_SC, ucp_Kaithi },+ { 596, PT_SC, ucp_Kannada },+ { 604, PT_SC, ucp_Katakana },+ { 613, PT_SC, ucp_Kayah_Li },+ { 622, PT_SC, ucp_Kharoshthi },+ { 633, PT_SC, ucp_Khitan_Small_Script },+ { 653, PT_SC, ucp_Khmer },+ { 659, PT_SC, ucp_Khojki },+ { 666, PT_SC, ucp_Khudawadi },+ { 676, PT_GC, ucp_L },+ { 678, PT_LAMP, 0 },+ { 681, PT_SC, ucp_Lao },+ { 685, PT_SC, ucp_Latin },+ { 691, PT_SC, ucp_Lepcha },+ { 698, PT_SC, ucp_Limbu },+ { 704, PT_SC, ucp_Linear_A },+ { 713, PT_SC, ucp_Linear_B },+ { 722, PT_SC, ucp_Lisu },+ { 727, PT_PC, ucp_Ll },+ { 730, PT_PC, ucp_Lm },+ { 733, PT_PC, ucp_Lo },+ { 736, PT_PC, ucp_Lt },+ { 739, PT_PC, ucp_Lu },+ { 742, PT_SC, ucp_Lycian },+ { 749, PT_SC, ucp_Lydian },+ { 756, PT_GC, ucp_M },+ { 758, PT_SC, ucp_Mahajani },+ { 767, PT_SC, ucp_Makasar },+ { 775, PT_SC, ucp_Malayalam },+ { 785, PT_SC, ucp_Mandaic },+ { 793, PT_SC, ucp_Manichaean },+ { 804, PT_SC, ucp_Marchen },+ { 812, PT_SC, ucp_Masaram_Gondi },+ { 826, PT_PC, ucp_Mc },+ { 829, PT_PC, ucp_Me },+ { 832, PT_SC, ucp_Medefaidrin },+ { 844, PT_SC, ucp_Meetei_Mayek },+ { 857, PT_SC, ucp_Mende_Kikakui },+ { 871, PT_SC, ucp_Meroitic_Cursive },+ { 888, PT_SC, ucp_Meroitic_Hieroglyphs },+ { 909, PT_SC, ucp_Miao },+ { 914, PT_PC, ucp_Mn },+ { 917, PT_SC, ucp_Modi },+ { 922, PT_SC, ucp_Mongolian },+ { 932, PT_SC, ucp_Mro },+ { 936, PT_SC, ucp_Multani },+ { 944, PT_SC, ucp_Myanmar },+ { 952, PT_GC, ucp_N },+ { 954, PT_SC, ucp_Nabataean },+ { 964, PT_SC, ucp_Nandinagari },+ { 976, PT_PC, ucp_Nd },+ { 979, PT_SC, ucp_New_Tai_Lue },+ { 991, PT_SC, ucp_Newa },+ { 996, PT_SC, ucp_Nko },+ { 1000, PT_PC, ucp_Nl },+ { 1003, PT_PC, ucp_No },+ { 1006, PT_SC, ucp_Nushu },+ { 1012, PT_SC, ucp_Nyiakeng_Puachue_Hmong },+ { 1035, PT_SC, ucp_Ogham },+ { 1041, PT_SC, ucp_Ol_Chiki },+ { 1050, PT_SC, ucp_Old_Hungarian },+ { 1064, PT_SC, ucp_Old_Italic },+ { 1075, PT_SC, ucp_Old_North_Arabian },+ { 1093, PT_SC, ucp_Old_Permic },+ { 1104, PT_SC, ucp_Old_Persian },+ { 1116, PT_SC, ucp_Old_Sogdian },+ { 1128, PT_SC, ucp_Old_South_Arabian },+ { 1146, PT_SC, ucp_Old_Turkic },+ { 1157, PT_SC, ucp_Oriya },+ { 1163, PT_SC, ucp_Osage },+ { 1169, PT_SC, ucp_Osmanya },+ { 1177, PT_GC, ucp_P },+ { 1179, PT_SC, ucp_Pahawh_Hmong },+ { 1192, PT_SC, ucp_Palmyrene },+ { 1202, PT_SC, ucp_Pau_Cin_Hau },+ { 1214, PT_PC, ucp_Pc },+ { 1217, PT_PC, ucp_Pd },+ { 1220, PT_PC, ucp_Pe },+ { 1223, PT_PC, ucp_Pf },+ { 1226, PT_SC, ucp_Phags_Pa },+ { 1235, PT_SC, ucp_Phoenician },+ { 1246, PT_PC, ucp_Pi },+ { 1249, PT_PC, ucp_Po },+ { 1252, PT_PC, ucp_Ps },+ { 1255, PT_SC, ucp_Psalter_Pahlavi },+ { 1271, PT_SC, ucp_Rejang },+ { 1278, PT_SC, ucp_Runic },+ { 1284, PT_GC, ucp_S },+ { 1286, PT_SC, ucp_Samaritan },+ { 1296, PT_SC, ucp_Saurashtra },+ { 1307, PT_PC, ucp_Sc },+ { 1310, PT_SC, ucp_Sharada },+ { 1318, PT_SC, ucp_Shavian },+ { 1326, PT_SC, ucp_Siddham },+ { 1334, PT_SC, ucp_SignWriting },+ { 1346, PT_SC, ucp_Sinhala },+ { 1354, PT_PC, ucp_Sk },+ { 1357, PT_PC, ucp_Sm },+ { 1360, PT_PC, ucp_So },+ { 1363, PT_SC, ucp_Sogdian },+ { 1371, PT_SC, ucp_Sora_Sompeng },+ { 1384, PT_SC, ucp_Soyombo },+ { 1392, PT_SC, ucp_Sundanese },+ { 1402, PT_SC, ucp_Syloti_Nagri },+ { 1415, PT_SC, ucp_Syriac },+ { 1422, PT_SC, ucp_Tagalog },+ { 1430, PT_SC, ucp_Tagbanwa },+ { 1439, PT_SC, ucp_Tai_Le },+ { 1446, PT_SC, ucp_Tai_Tham },+ { 1455, PT_SC, ucp_Tai_Viet },+ { 1464, PT_SC, ucp_Takri },+ { 1470, PT_SC, ucp_Tamil },+ { 1476, PT_SC, ucp_Tangut },+ { 1483, PT_SC, ucp_Telugu },+ { 1490, PT_SC, ucp_Thaana },+ { 1497, PT_SC, ucp_Thai },+ { 1502, PT_SC, ucp_Tibetan },+ { 1510, PT_SC, ucp_Tifinagh },+ { 1519, PT_SC, ucp_Tirhuta },+ { 1527, PT_SC, ucp_Ugaritic },+ { 1536, PT_SC, ucp_Unknown },+ { 1544, PT_SC, ucp_Vai },+ { 1548, PT_SC, ucp_Wancho },+ { 1555, PT_SC, ucp_Warang_Citi },+ { 1567, PT_ALNUM, 0 },+ { 1571, PT_PXSPACE, 0 },+ { 1575, PT_SPACE, 0 },+ { 1579, PT_UCNC, 0 },+ { 1583, PT_WORD, 0 },+ { 1587, PT_SC, ucp_Yezidi },+ { 1594, PT_SC, ucp_Yi },+ { 1597, PT_GC, ucp_Z },+ { 1599, PT_SC, ucp_Zanabazar_Square },+ { 1616, PT_PC, ucp_Zl },+ { 1619, PT_PC, ucp_Zp },+ { 1622, PT_PC, ucp_Zs }+};++const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);++#endif /* SUPPORT_UNICODE */++/* End of pcre2_tables.c */
+ src/c/pcre2/src/pcre2_ucd.c view
@@ -0,0 +1,4538 @@+/* This module is generated by the maint/MultiStage2.py script.+Do not modify it by hand. Instead modify the script and run it+to regenerate this code.++As well as being part of the PCRE2 library, this module is #included+by the pcre2test program, which redefines the PRIV macro to change+table names from _pcre2_xxx to xxxx, thereby avoiding name clashes+with the library. At present, just one of these tables is actually+needed. */++#ifndef PCRE2_PCRE2TEST++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include "pcre2_internal.h"++#endif /* PCRE2_PCRE2TEST */++/* Unicode character database. */+/* This file was autogenerated by the MultiStage2.py script. */+/* Total size: 101044 bytes, block size: 128. */++/* The tables herein are needed only when UCP support is built,+and in PCRE2 that happens automatically with UTF support.+This module should not be referenced otherwise, so+it should not matter whether it is compiled or not. However+a comment was received about space saving - maybe the guy linked+all the modules rather than using a library - so we include a+condition to cut out the tables when not needed. But don't leave+a totally empty module because some compilers barf at that.+Instead, just supply some small dummy tables. */++#ifndef SUPPORT_UNICODE+const ucd_record PRIV(ucd_records)[] = {{0,0,0,0,0,0,0 }};+const uint16_t PRIV(ucd_stage1)[] = {0};+const uint16_t PRIV(ucd_stage2)[] = {0};+const uint32_t PRIV(ucd_caseless_sets)[] = {0};+#else++const char *PRIV(unicode_version) = "13.0.0";++/* If the 32-bit library is run in non-32-bit mode, character values+greater than 0x10ffff may be encountered. For these we set up a+special record. */++#if PCRE2_CODE_UNIT_WIDTH == 32+const ucd_record PRIV(dummy_ucd_record)[] = {{+ ucp_Unknown, /* script */+ ucp_Cn, /* type unassigned */+ ucp_gbOther, /* grapheme break property */+ 0, /* case set */+ 0, /* other case */+ ucp_Unknown, /* script extension */+ 0, /* dummy filler */+ }};+#endif++/* When recompiling tables with a new Unicode version, please check the+types in this structure definition from pcre2_internal.h (the actual+field names will be different):++typedef struct {+uint8_t property_0;+uint8_t property_1;+uint8_t property_2;+uint8_t property_3;+pcre_int32 property_4;+pcre_int16 property_5;+uint16_t property_6;+} ucd_record;+*/++/* This table contains lists of characters that are caseless sets of+more than one character. Each list is terminated by NOTACHAR. */++const uint32_t PRIV(ucd_caseless_sets)[] = {+ NOTACHAR,+ 0x0053, 0x0073, 0x017f, NOTACHAR,+ 0x01c4, 0x01c5, 0x01c6, NOTACHAR,+ 0x01c7, 0x01c8, 0x01c9, NOTACHAR,+ 0x01ca, 0x01cb, 0x01cc, NOTACHAR,+ 0x01f1, 0x01f2, 0x01f3, NOTACHAR,+ 0x0345, 0x0399, 0x03b9, 0x1fbe, NOTACHAR,+ 0x00b5, 0x039c, 0x03bc, NOTACHAR,+ 0x03a3, 0x03c2, 0x03c3, NOTACHAR,+ 0x0392, 0x03b2, 0x03d0, NOTACHAR,+ 0x0398, 0x03b8, 0x03d1, 0x03f4, NOTACHAR,+ 0x03a6, 0x03c6, 0x03d5, NOTACHAR,+ 0x03a0, 0x03c0, 0x03d6, NOTACHAR,+ 0x039a, 0x03ba, 0x03f0, NOTACHAR,+ 0x03a1, 0x03c1, 0x03f1, NOTACHAR,+ 0x0395, 0x03b5, 0x03f5, NOTACHAR,+ 0x0412, 0x0432, 0x1c80, NOTACHAR,+ 0x0414, 0x0434, 0x1c81, NOTACHAR,+ 0x041e, 0x043e, 0x1c82, NOTACHAR,+ 0x0421, 0x0441, 0x1c83, NOTACHAR,+ 0x0422, 0x0442, 0x1c84, 0x1c85, NOTACHAR,+ 0x042a, 0x044a, 0x1c86, NOTACHAR,+ 0x0462, 0x0463, 0x1c87, NOTACHAR,+ 0x1e60, 0x1e61, 0x1e9b, NOTACHAR,+ 0x03a9, 0x03c9, 0x2126, NOTACHAR,+ 0x004b, 0x006b, 0x212a, NOTACHAR,+ 0x00c5, 0x00e5, 0x212b, NOTACHAR,+ 0x1c88, 0xa64a, 0xa64b, NOTACHAR,+};++/* When #included in pcre2test, we don't need the table of digit+sets, nor the the large main UCD tables. */++#ifndef PCRE2_PCRE2TEST++/* This table lists the code points for the '9' characters in each+set of decimal digits. It is used to ensure that all the digits in+a script run come from the same set. */++const uint32_t PRIV(ucd_digit_sets)[] = {+ 65, /* Number of subsequent values */+ 0x00039, 0x00669, 0x006f9, 0x007c9, 0x0096f, 0x009ef, 0x00a6f, 0x00aef,+ 0x00b6f, 0x00bef, 0x00c6f, 0x00cef, 0x00d6f, 0x00def, 0x00e59, 0x00ed9,+ 0x00f29, 0x01049, 0x01099, 0x017e9, 0x01819, 0x0194f, 0x019d9, 0x01a89,+ 0x01a99, 0x01b59, 0x01bb9, 0x01c49, 0x01c59, 0x0a629, 0x0a8d9, 0x0a909,+ 0x0a9d9, 0x0a9f9, 0x0aa59, 0x0abf9, 0x0ff19, 0x104a9, 0x10d39, 0x1106f,+ 0x110f9, 0x1113f, 0x111d9, 0x112f9, 0x11459, 0x114d9, 0x11659, 0x116c9,+ 0x11739, 0x118e9, 0x11959, 0x11c59, 0x11d59, 0x11da9, 0x16a69, 0x16b59,+ 0x1d7d7, 0x1d7e1, 0x1d7eb, 0x1d7f5, 0x1d7ff, 0x1e149, 0x1e2f9, 0x1e959,+ 0x1fbf9,+};++/* This vector is a list of lists of scripts for the Script Extension+property. Each sublist is zero-terminated. */++const uint8_t PRIV(ucd_script_sets)[] = {+ /* 0 */ 0,+ /* 1 */ 1, 11, 0,+ /* 4 */ 1, 144, 0,+ /* 7 */ 1, 50, 0,+ /* 10 */ 1, 56, 0,+ /* 13 */ 3, 15, 0,+ /* 16 */ 4, 23, 0,+ /* 19 */ 6, 84, 0,+ /* 22 */ 12, 36, 0,+ /* 25 */ 13, 18, 0,+ /* 28 */ 13, 34, 0,+ /* 31 */ 13, 118, 0,+ /* 34 */ 13, 50, 0,+ /* 37 */ 15, 107, 0,+ /* 40 */ 15, 150, 0,+ /* 43 */ 15, 100, 0,+ /* 46 */ 15, 54, 0,+ /* 49 */ 17, 34, 0,+ /* 52 */ 107, 54, 0,+ /* 55 */ 21, 108, 0,+ /* 58 */ 22, 129, 0,+ /* 61 */ 23, 34, 0,+ /* 64 */ 27, 30, 0,+ /* 67 */ 29, 150, 0,+ /* 70 */ 34, 38, 0,+ /* 73 */ 38, 65, 0,+ /* 76 */ 1, 50, 56, 0,+ /* 80 */ 1, 56, 156, 0,+ /* 84 */ 3, 96, 49, 0,+ /* 88 */ 96, 39, 53, 0,+ /* 92 */ 12, 110, 36, 0,+ /* 96 */ 15, 107, 29, 0,+ /* 100 */ 15, 107, 34, 0,+ /* 104 */ 23, 27, 30, 0,+ /* 108 */ 69, 34, 39, 0,+ /* 112 */ 3, 15, 107, 29, 0,+ /* 117 */ 7, 25, 52, 51, 0,+ /* 122 */ 15, 142, 85, 111, 0,+ /* 127 */ 1, 144, 50, 56, 156, 0,+ /* 133 */ 4, 24, 23, 27, 30, 0,+ /* 139 */ 4, 24, 23, 27, 30, 61, 0,+ /* 146 */ 15, 29, 37, 44, 54, 55, 0,+ /* 153 */ 132, 1, 95, 112, 121, 144, 148, 50, 0,+ /* 162 */ 3, 15, 107, 29, 150, 44, 55, 124, 0,+ /* 171 */ 15, 142, 21, 22, 108, 85, 111, 114, 109, 102, 124, 0,+ /* 183 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 54, 55, 124, 0,+ /* 196 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 100, 54, 55, 124, 0,+ /* 210 */ 15, 142, 21, 22, 108, 29, 85, 111, 114, 150, 109, 102, 124, 0,+ /* 224 */ 15, 142, 21, 22, 108, 29, 85, 111, 37, 114, 150, 109, 102, 124, 0,+ /* 239 */ 3, 15, 142, 143, 138, 107, 21, 22, 29, 111, 37, 150, 44, 109, 48, 49, 102, 54, 55, 124, 0,+ /* 260 */ 3, 15, 142, 143, 138, 107, 21, 22, 29, 35, 111, 37, 150, 44, 109, 48, 49, 102, 54, 55, 124, 0,+ /* 282 */+};++/* These are the main two-stage UCD tables. The fields in each record are:+script (8 bits), character type (8 bits), grapheme break property (8 bits),+offset to multichar other cases or zero (8 bits), offset to other case+or zero (32 bits, signed), script extension (16 bits, signed), and a dummy+16-bit field to make the whole thing a multiple of 4 bytes. */++const ucd_record PRIV(ucd_records)[] = { /* 11700 bytes, record size 12 */+ { 10, 0, 2, 0, 0, 10, 256, }, /* 0 */+ { 10, 0, 2, 0, 0, 10, 0, }, /* 1 */+ { 10, 0, 1, 0, 0, 10, 0, }, /* 2 */+ { 10, 0, 0, 0, 0, 10, 0, }, /* 3 */+ { 10, 29, 12, 0, 0, 10, 0, }, /* 4 */+ { 10, 21, 12, 0, 0, 10, 0, }, /* 5 */+ { 10, 23, 12, 0, 0, 10, 0, }, /* 6 */+ { 10, 22, 12, 0, 0, 10, 0, }, /* 7 */+ { 10, 18, 12, 0, 0, 10, 0, }, /* 8 */+ { 10, 25, 12, 0, 0, 10, 0, }, /* 9 */+ { 10, 17, 12, 0, 0, 10, 0, }, /* 10 */+ { 10, 13, 12, 0, 0, 10, 0, }, /* 11 */+ { 34, 9, 12, 0, 32, 34, 0, }, /* 12 */+ { 34, 9, 12, 100, 32, 34, 0, }, /* 13 */+ { 34, 9, 12, 1, 32, 34, 0, }, /* 14 */+ { 10, 24, 12, 0, 0, 10, 0, }, /* 15 */+ { 10, 16, 12, 0, 0, 10, 0, }, /* 16 */+ { 34, 5, 12, 0, -32, 34, 0, }, /* 17 */+ { 34, 5, 12, 100, -32, 34, 0, }, /* 18 */+ { 34, 5, 12, 1, -32, 34, 0, }, /* 19 */+ { 10, 26, 12, 0, 0, 10, 0, }, /* 20 */+ { 10, 26, 14, 0, 0, 10, 0, }, /* 21 */+ { 34, 7, 12, 0, 0, 34, 0, }, /* 22 */+ { 10, 20, 12, 0, 0, 10, 0, }, /* 23 */+ { 10, 1, 2, 0, 0, 10, 0, }, /* 24 */+ { 10, 15, 12, 0, 0, 10, 0, }, /* 25 */+ { 10, 5, 12, 26, 775, 10, 0, }, /* 26 */+ { 10, 19, 12, 0, 0, 10, 0, }, /* 27 */+ { 34, 9, 12, 104, 32, 34, 0, }, /* 28 */+ { 34, 5, 12, 0, 7615, 34, 0, }, /* 29 */+ { 34, 5, 12, 104, -32, 34, 0, }, /* 30 */+ { 34, 5, 12, 0, 121, 34, 0, }, /* 31 */+ { 34, 9, 12, 0, 1, 34, 0, }, /* 32 */+ { 34, 5, 12, 0, -1, 34, 0, }, /* 33 */+ { 34, 9, 12, 0, 0, 34, 0, }, /* 34 */+ { 34, 5, 12, 0, 0, 34, 0, }, /* 35 */+ { 34, 9, 12, 0, -121, 34, 0, }, /* 36 */+ { 34, 5, 12, 1, -268, 34, 0, }, /* 37 */+ { 34, 5, 12, 0, 195, 34, 0, }, /* 38 */+ { 34, 9, 12, 0, 210, 34, 0, }, /* 39 */+ { 34, 9, 12, 0, 206, 34, 0, }, /* 40 */+ { 34, 9, 12, 0, 205, 34, 0, }, /* 41 */+ { 34, 9, 12, 0, 79, 34, 0, }, /* 42 */+ { 34, 9, 12, 0, 202, 34, 0, }, /* 43 */+ { 34, 9, 12, 0, 203, 34, 0, }, /* 44 */+ { 34, 9, 12, 0, 207, 34, 0, }, /* 45 */+ { 34, 5, 12, 0, 97, 34, 0, }, /* 46 */+ { 34, 9, 12, 0, 211, 34, 0, }, /* 47 */+ { 34, 9, 12, 0, 209, 34, 0, }, /* 48 */+ { 34, 5, 12, 0, 163, 34, 0, }, /* 49 */+ { 34, 9, 12, 0, 213, 34, 0, }, /* 50 */+ { 34, 5, 12, 0, 130, 34, 0, }, /* 51 */+ { 34, 9, 12, 0, 214, 34, 0, }, /* 52 */+ { 34, 9, 12, 0, 218, 34, 0, }, /* 53 */+ { 34, 9, 12, 0, 217, 34, 0, }, /* 54 */+ { 34, 9, 12, 0, 219, 34, 0, }, /* 55 */+ { 34, 5, 12, 0, 56, 34, 0, }, /* 56 */+ { 34, 9, 12, 5, 2, 34, 0, }, /* 57 */+ { 34, 8, 12, 5, 1, 34, 0, }, /* 58 */+ { 34, 5, 12, 5, -2, 34, 0, }, /* 59 */+ { 34, 9, 12, 9, 2, 34, 0, }, /* 60 */+ { 34, 8, 12, 9, 1, 34, 0, }, /* 61 */+ { 34, 5, 12, 9, -2, 34, 0, }, /* 62 */+ { 34, 9, 12, 13, 2, 34, 0, }, /* 63 */+ { 34, 8, 12, 13, 1, 34, 0, }, /* 64 */+ { 34, 5, 12, 13, -2, 34, 0, }, /* 65 */+ { 34, 5, 12, 0, -79, 34, 0, }, /* 66 */+ { 34, 9, 12, 17, 2, 34, 0, }, /* 67 */+ { 34, 8, 12, 17, 1, 34, 0, }, /* 68 */+ { 34, 5, 12, 17, -2, 34, 0, }, /* 69 */+ { 34, 9, 12, 0, -97, 34, 0, }, /* 70 */+ { 34, 9, 12, 0, -56, 34, 0, }, /* 71 */+ { 34, 9, 12, 0, -130, 34, 0, }, /* 72 */+ { 34, 9, 12, 0, 10795, 34, 0, }, /* 73 */+ { 34, 9, 12, 0, -163, 34, 0, }, /* 74 */+ { 34, 9, 12, 0, 10792, 34, 0, }, /* 75 */+ { 34, 5, 12, 0, 10815, 34, 0, }, /* 76 */+ { 34, 9, 12, 0, -195, 34, 0, }, /* 77 */+ { 34, 9, 12, 0, 69, 34, 0, }, /* 78 */+ { 34, 9, 12, 0, 71, 34, 0, }, /* 79 */+ { 34, 5, 12, 0, 10783, 34, 0, }, /* 80 */+ { 34, 5, 12, 0, 10780, 34, 0, }, /* 81 */+ { 34, 5, 12, 0, 10782, 34, 0, }, /* 82 */+ { 34, 5, 12, 0, -210, 34, 0, }, /* 83 */+ { 34, 5, 12, 0, -206, 34, 0, }, /* 84 */+ { 34, 5, 12, 0, -205, 34, 0, }, /* 85 */+ { 34, 5, 12, 0, -202, 34, 0, }, /* 86 */+ { 34, 5, 12, 0, -203, 34, 0, }, /* 87 */+ { 34, 5, 12, 0, 42319, 34, 0, }, /* 88 */+ { 34, 5, 12, 0, 42315, 34, 0, }, /* 89 */+ { 34, 5, 12, 0, -207, 34, 0, }, /* 90 */+ { 34, 5, 12, 0, 42280, 34, 0, }, /* 91 */+ { 34, 5, 12, 0, 42308, 34, 0, }, /* 92 */+ { 34, 5, 12, 0, -209, 34, 0, }, /* 93 */+ { 34, 5, 12, 0, -211, 34, 0, }, /* 94 */+ { 34, 5, 12, 0, 10743, 34, 0, }, /* 95 */+ { 34, 5, 12, 0, 42305, 34, 0, }, /* 96 */+ { 34, 5, 12, 0, 10749, 34, 0, }, /* 97 */+ { 34, 5, 12, 0, -213, 34, 0, }, /* 98 */+ { 34, 5, 12, 0, -214, 34, 0, }, /* 99 */+ { 34, 5, 12, 0, 10727, 34, 0, }, /* 100 */+ { 34, 5, 12, 0, -218, 34, 0, }, /* 101 */+ { 34, 5, 12, 0, 42307, 34, 0, }, /* 102 */+ { 34, 5, 12, 0, 42282, 34, 0, }, /* 103 */+ { 34, 5, 12, 0, -69, 34, 0, }, /* 104 */+ { 34, 5, 12, 0, -217, 34, 0, }, /* 105 */+ { 34, 5, 12, 0, -71, 34, 0, }, /* 106 */+ { 34, 5, 12, 0, -219, 34, 0, }, /* 107 */+ { 34, 5, 12, 0, 42261, 34, 0, }, /* 108 */+ { 34, 5, 12, 0, 42258, 34, 0, }, /* 109 */+ { 34, 6, 12, 0, 0, 34, 0, }, /* 110 */+ { 10, 6, 12, 0, 0, 10, 0, }, /* 111 */+ { 4, 24, 12, 0, 0, 4, 0, }, /* 112 */+ { 28, 12, 3, 0, 0, 28, 0, }, /* 113 */+ { 28, 12, 3, 0, 0, 20, 0, }, /* 114 */+ { 28, 12, 3, 21, 116, 20, 0, }, /* 115 */+ { 28, 12, 3, 0, 0, 34, 0, }, /* 116 */+ { 20, 9, 12, 0, 1, 20, 0, }, /* 117 */+ { 20, 5, 12, 0, -1, 20, 0, }, /* 118 */+ { 20, 24, 12, 0, 0, 20, 0, }, /* 119 */+ { 0, 2, 12, 0, 0, 0, 0, }, /* 120 */+ { 20, 6, 12, 0, 0, 20, 0, }, /* 121 */+ { 20, 5, 12, 0, 130, 20, 0, }, /* 122 */+ { 20, 9, 12, 0, 116, 20, 0, }, /* 123 */+ { 20, 9, 12, 0, 38, 20, 0, }, /* 124 */+ { 20, 9, 12, 0, 37, 20, 0, }, /* 125 */+ { 20, 9, 12, 0, 64, 20, 0, }, /* 126 */+ { 20, 9, 12, 0, 63, 20, 0, }, /* 127 */+ { 20, 5, 12, 0, 0, 20, 0, }, /* 128 */+ { 20, 9, 12, 0, 32, 20, 0, }, /* 129 */+ { 20, 9, 12, 34, 32, 20, 0, }, /* 130 */+ { 20, 9, 12, 59, 32, 20, 0, }, /* 131 */+ { 20, 9, 12, 38, 32, 20, 0, }, /* 132 */+ { 20, 9, 12, 21, 32, 20, 0, }, /* 133 */+ { 20, 9, 12, 51, 32, 20, 0, }, /* 134 */+ { 20, 9, 12, 26, 32, 20, 0, }, /* 135 */+ { 20, 9, 12, 47, 32, 20, 0, }, /* 136 */+ { 20, 9, 12, 55, 32, 20, 0, }, /* 137 */+ { 20, 9, 12, 30, 32, 20, 0, }, /* 138 */+ { 20, 9, 12, 43, 32, 20, 0, }, /* 139 */+ { 20, 9, 12, 96, 32, 20, 0, }, /* 140 */+ { 20, 5, 12, 0, -38, 20, 0, }, /* 141 */+ { 20, 5, 12, 0, -37, 20, 0, }, /* 142 */+ { 20, 5, 12, 0, -32, 20, 0, }, /* 143 */+ { 20, 5, 12, 34, -32, 20, 0, }, /* 144 */+ { 20, 5, 12, 59, -32, 20, 0, }, /* 145 */+ { 20, 5, 12, 38, -32, 20, 0, }, /* 146 */+ { 20, 5, 12, 21, -116, 20, 0, }, /* 147 */+ { 20, 5, 12, 51, -32, 20, 0, }, /* 148 */+ { 20, 5, 12, 26, -775, 20, 0, }, /* 149 */+ { 20, 5, 12, 47, -32, 20, 0, }, /* 150 */+ { 20, 5, 12, 55, -32, 20, 0, }, /* 151 */+ { 20, 5, 12, 30, 1, 20, 0, }, /* 152 */+ { 20, 5, 12, 30, -32, 20, 0, }, /* 153 */+ { 20, 5, 12, 43, -32, 20, 0, }, /* 154 */+ { 20, 5, 12, 96, -32, 20, 0, }, /* 155 */+ { 20, 5, 12, 0, -64, 20, 0, }, /* 156 */+ { 20, 5, 12, 0, -63, 20, 0, }, /* 157 */+ { 20, 9, 12, 0, 8, 20, 0, }, /* 158 */+ { 20, 5, 12, 34, -30, 20, 0, }, /* 159 */+ { 20, 5, 12, 38, -25, 20, 0, }, /* 160 */+ { 20, 9, 12, 0, 0, 20, 0, }, /* 161 */+ { 20, 5, 12, 43, -15, 20, 0, }, /* 162 */+ { 20, 5, 12, 47, -22, 20, 0, }, /* 163 */+ { 20, 5, 12, 0, -8, 20, 0, }, /* 164 */+ { 11, 9, 12, 0, 1, 11, 0, }, /* 165 */+ { 11, 5, 12, 0, -1, 11, 0, }, /* 166 */+ { 20, 5, 12, 51, -54, 20, 0, }, /* 167 */+ { 20, 5, 12, 55, -48, 20, 0, }, /* 168 */+ { 20, 5, 12, 0, 7, 20, 0, }, /* 169 */+ { 20, 5, 12, 0, -116, 20, 0, }, /* 170 */+ { 20, 9, 12, 38, -60, 20, 0, }, /* 171 */+ { 20, 5, 12, 59, -64, 20, 0, }, /* 172 */+ { 20, 25, 12, 0, 0, 20, 0, }, /* 173 */+ { 20, 9, 12, 0, -7, 20, 0, }, /* 174 */+ { 20, 9, 12, 0, -130, 20, 0, }, /* 175 */+ { 13, 9, 12, 0, 80, 13, 0, }, /* 176 */+ { 13, 9, 12, 0, 32, 13, 0, }, /* 177 */+ { 13, 9, 12, 63, 32, 13, 0, }, /* 178 */+ { 13, 9, 12, 67, 32, 13, 0, }, /* 179 */+ { 13, 9, 12, 71, 32, 13, 0, }, /* 180 */+ { 13, 9, 12, 75, 32, 13, 0, }, /* 181 */+ { 13, 9, 12, 79, 32, 13, 0, }, /* 182 */+ { 13, 9, 12, 84, 32, 13, 0, }, /* 183 */+ { 13, 5, 12, 0, -32, 13, 0, }, /* 184 */+ { 13, 5, 12, 63, -32, 13, 0, }, /* 185 */+ { 13, 5, 12, 67, -32, 13, 0, }, /* 186 */+ { 13, 5, 12, 71, -32, 13, 0, }, /* 187 */+ { 13, 5, 12, 75, -32, 13, 0, }, /* 188 */+ { 13, 5, 12, 79, -32, 13, 0, }, /* 189 */+ { 13, 5, 12, 84, -32, 13, 0, }, /* 190 */+ { 13, 5, 12, 0, -80, 13, 0, }, /* 191 */+ { 13, 9, 12, 0, 1, 13, 0, }, /* 192 */+ { 13, 5, 12, 0, -1, 13, 0, }, /* 193 */+ { 13, 9, 12, 88, 1, 13, 0, }, /* 194 */+ { 13, 5, 12, 88, -1, 13, 0, }, /* 195 */+ { 13, 26, 12, 0, 0, 13, 0, }, /* 196 */+ { 13, 12, 3, 0, 0, -31, 0, }, /* 197 */+ { 13, 12, 3, 0, 0, -25, 0, }, /* 198 */+ { 28, 12, 3, 0, 0, -28, 0, }, /* 199 */+ { 13, 11, 3, 0, 0, 13, 0, }, /* 200 */+ { 13, 9, 12, 0, 15, 13, 0, }, /* 201 */+ { 13, 5, 12, 0, -15, 13, 0, }, /* 202 */+ { 2, 9, 12, 0, 48, 2, 0, }, /* 203 */+ { 2, 6, 12, 0, 0, 2, 0, }, /* 204 */+ { 2, 21, 12, 0, 0, 2, 0, }, /* 205 */+ { 2, 5, 12, 0, 0, 2, 0, }, /* 206 */+ { 2, 5, 12, 0, -48, 2, 0, }, /* 207 */+ { 2, 17, 12, 0, 0, 2, 0, }, /* 208 */+ { 2, 26, 12, 0, 0, 2, 0, }, /* 209 */+ { 2, 23, 12, 0, 0, 2, 0, }, /* 210 */+ { 26, 12, 3, 0, 0, 26, 0, }, /* 211 */+ { 26, 17, 12, 0, 0, 26, 0, }, /* 212 */+ { 26, 21, 12, 0, 0, 26, 0, }, /* 213 */+ { 26, 7, 12, 0, 0, 26, 0, }, /* 214 */+ { 1, 1, 4, 0, 0, 1, 0, }, /* 215 */+ { 10, 1, 4, 0, 0, 10, 0, }, /* 216 */+ { 1, 25, 12, 0, 0, 1, 0, }, /* 217 */+ { 1, 21, 12, 0, 0, 1, 0, }, /* 218 */+ { 1, 23, 12, 0, 0, 1, 0, }, /* 219 */+ { 10, 21, 12, 0, 0, -127, 0, }, /* 220 */+ { 1, 26, 12, 0, 0, 1, 0, }, /* 221 */+ { 1, 12, 3, 0, 0, 1, 0, }, /* 222 */+ { 1, 1, 2, 0, 0, -76, 0, }, /* 223 */+ { 1, 7, 12, 0, 0, 1, 0, }, /* 224 */+ { 10, 6, 12, 0, 0, -153, 0, }, /* 225 */+ { 28, 12, 3, 0, 0, -7, 0, }, /* 226 */+ { 1, 13, 12, 0, 0, -80, 0, }, /* 227 */+ { 1, 21, 12, 0, 0, -4, 0, }, /* 228 */+ { 1, 6, 12, 0, 0, 1, 0, }, /* 229 */+ { 1, 13, 12, 0, 0, 1, 0, }, /* 230 */+ { 50, 21, 12, 0, 0, 50, 0, }, /* 231 */+ { 50, 1, 4, 0, 0, 50, 0, }, /* 232 */+ { 50, 7, 12, 0, 0, 50, 0, }, /* 233 */+ { 50, 12, 3, 0, 0, 50, 0, }, /* 234 */+ { 56, 7, 12, 0, 0, 56, 0, }, /* 235 */+ { 56, 12, 3, 0, 0, 56, 0, }, /* 236 */+ { 64, 13, 12, 0, 0, 64, 0, }, /* 237 */+ { 64, 7, 12, 0, 0, 64, 0, }, /* 238 */+ { 64, 12, 3, 0, 0, 64, 0, }, /* 239 */+ { 64, 6, 12, 0, 0, 64, 0, }, /* 240 */+ { 64, 26, 12, 0, 0, 64, 0, }, /* 241 */+ { 64, 21, 12, 0, 0, 64, 0, }, /* 242 */+ { 64, 23, 12, 0, 0, 64, 0, }, /* 243 */+ { 90, 7, 12, 0, 0, 90, 0, }, /* 244 */+ { 90, 12, 3, 0, 0, 90, 0, }, /* 245 */+ { 90, 6, 12, 0, 0, 90, 0, }, /* 246 */+ { 90, 21, 12, 0, 0, 90, 0, }, /* 247 */+ { 95, 7, 12, 0, 0, 95, 0, }, /* 248 */+ { 95, 12, 3, 0, 0, 95, 0, }, /* 249 */+ { 95, 21, 12, 0, 0, 95, 0, }, /* 250 */+ { 15, 12, 3, 0, 0, 15, 0, }, /* 251 */+ { 15, 10, 5, 0, 0, 15, 0, }, /* 252 */+ { 15, 7, 12, 0, 0, 15, 0, }, /* 253 */+ { 28, 12, 3, 0, 0, -196, 0, }, /* 254 */+ { 28, 12, 3, 0, 0, -183, 0, }, /* 255 */+ { 10, 21, 12, 0, 0, -239, 0, }, /* 256 */+ { 10, 21, 12, 0, 0, -260, 0, }, /* 257 */+ { 15, 13, 12, 0, 0, -122, 0, }, /* 258 */+ { 15, 21, 12, 0, 0, 15, 0, }, /* 259 */+ { 15, 6, 12, 0, 0, 15, 0, }, /* 260 */+ { 3, 7, 12, 0, 0, 3, 0, }, /* 261 */+ { 3, 12, 3, 0, 0, 3, 0, }, /* 262 */+ { 3, 10, 5, 0, 0, 3, 0, }, /* 263 */+ { 3, 10, 3, 0, 0, 3, 0, }, /* 264 */+ { 3, 13, 12, 0, 0, -84, 0, }, /* 265 */+ { 3, 23, 12, 0, 0, 3, 0, }, /* 266 */+ { 3, 15, 12, 0, 0, 3, 0, }, /* 267 */+ { 3, 26, 12, 0, 0, 3, 0, }, /* 268 */+ { 3, 21, 12, 0, 0, 3, 0, }, /* 269 */+ { 22, 12, 3, 0, 0, 22, 0, }, /* 270 */+ { 22, 10, 5, 0, 0, 22, 0, }, /* 271 */+ { 22, 7, 12, 0, 0, 22, 0, }, /* 272 */+ { 22, 13, 12, 0, 0, -58, 0, }, /* 273 */+ { 22, 21, 12, 0, 0, 22, 0, }, /* 274 */+ { 21, 12, 3, 0, 0, 21, 0, }, /* 275 */+ { 21, 10, 5, 0, 0, 21, 0, }, /* 276 */+ { 21, 7, 12, 0, 0, 21, 0, }, /* 277 */+ { 21, 13, 12, 0, 0, -55, 0, }, /* 278 */+ { 21, 21, 12, 0, 0, 21, 0, }, /* 279 */+ { 21, 23, 12, 0, 0, 21, 0, }, /* 280 */+ { 44, 12, 3, 0, 0, 44, 0, }, /* 281 */+ { 44, 10, 5, 0, 0, 44, 0, }, /* 282 */+ { 44, 7, 12, 0, 0, 44, 0, }, /* 283 */+ { 44, 10, 3, 0, 0, 44, 0, }, /* 284 */+ { 44, 13, 12, 0, 0, 44, 0, }, /* 285 */+ { 44, 26, 12, 0, 0, 44, 0, }, /* 286 */+ { 44, 15, 12, 0, 0, 44, 0, }, /* 287 */+ { 54, 12, 3, 0, 0, 54, 0, }, /* 288 */+ { 54, 7, 12, 0, 0, 54, 0, }, /* 289 */+ { 54, 10, 3, 0, 0, 54, 0, }, /* 290 */+ { 54, 10, 5, 0, 0, 54, 0, }, /* 291 */+ { 54, 13, 12, 0, 0, -52, 0, }, /* 292 */+ { 54, 15, 12, 0, 0, -52, 0, }, /* 293 */+ { 54, 26, 12, 0, 0, -52, 0, }, /* 294 */+ { 54, 26, 12, 0, 0, 54, 0, }, /* 295 */+ { 54, 23, 12, 0, 0, 54, 0, }, /* 296 */+ { 55, 12, 3, 0, 0, 55, 0, }, /* 297 */+ { 55, 10, 5, 0, 0, 55, 0, }, /* 298 */+ { 55, 7, 12, 0, 0, 55, 0, }, /* 299 */+ { 55, 13, 12, 0, 0, 55, 0, }, /* 300 */+ { 55, 21, 12, 0, 0, 55, 0, }, /* 301 */+ { 55, 15, 12, 0, 0, 55, 0, }, /* 302 */+ { 55, 26, 12, 0, 0, 55, 0, }, /* 303 */+ { 29, 7, 12, 0, 0, 29, 0, }, /* 304 */+ { 29, 12, 3, 0, 0, 29, 0, }, /* 305 */+ { 29, 10, 5, 0, 0, 29, 0, }, /* 306 */+ { 29, 21, 12, 0, 0, 29, 0, }, /* 307 */+ { 29, 10, 3, 0, 0, 29, 0, }, /* 308 */+ { 29, 13, 12, 0, 0, -67, 0, }, /* 309 */+ { 37, 12, 3, 0, 0, 37, 0, }, /* 310 */+ { 37, 10, 5, 0, 0, 37, 0, }, /* 311 */+ { 37, 7, 12, 0, 0, 37, 0, }, /* 312 */+ { 37, 10, 3, 0, 0, 37, 0, }, /* 313 */+ { 37, 7, 4, 0, 0, 37, 0, }, /* 314 */+ { 37, 26, 12, 0, 0, 37, 0, }, /* 315 */+ { 37, 15, 12, 0, 0, 37, 0, }, /* 316 */+ { 37, 13, 12, 0, 0, 37, 0, }, /* 317 */+ { 48, 12, 3, 0, 0, 48, 0, }, /* 318 */+ { 48, 10, 5, 0, 0, 48, 0, }, /* 319 */+ { 48, 7, 12, 0, 0, 48, 0, }, /* 320 */+ { 48, 10, 3, 0, 0, 48, 0, }, /* 321 */+ { 48, 13, 12, 0, 0, 48, 0, }, /* 322 */+ { 48, 21, 12, 0, 0, 48, 0, }, /* 323 */+ { 57, 7, 12, 0, 0, 57, 0, }, /* 324 */+ { 57, 12, 3, 0, 0, 57, 0, }, /* 325 */+ { 57, 7, 5, 0, 0, 57, 0, }, /* 326 */+ { 57, 6, 12, 0, 0, 57, 0, }, /* 327 */+ { 57, 21, 12, 0, 0, 57, 0, }, /* 328 */+ { 57, 13, 12, 0, 0, 57, 0, }, /* 329 */+ { 33, 7, 12, 0, 0, 33, 0, }, /* 330 */+ { 33, 12, 3, 0, 0, 33, 0, }, /* 331 */+ { 33, 7, 5, 0, 0, 33, 0, }, /* 332 */+ { 33, 6, 12, 0, 0, 33, 0, }, /* 333 */+ { 33, 13, 12, 0, 0, 33, 0, }, /* 334 */+ { 58, 7, 12, 0, 0, 58, 0, }, /* 335 */+ { 58, 26, 12, 0, 0, 58, 0, }, /* 336 */+ { 58, 21, 12, 0, 0, 58, 0, }, /* 337 */+ { 58, 12, 3, 0, 0, 58, 0, }, /* 338 */+ { 58, 13, 12, 0, 0, 58, 0, }, /* 339 */+ { 58, 15, 12, 0, 0, 58, 0, }, /* 340 */+ { 58, 22, 12, 0, 0, 58, 0, }, /* 341 */+ { 58, 18, 12, 0, 0, 58, 0, }, /* 342 */+ { 58, 10, 5, 0, 0, 58, 0, }, /* 343 */+ { 39, 7, 12, 0, 0, 39, 0, }, /* 344 */+ { 39, 10, 12, 0, 0, 39, 0, }, /* 345 */+ { 39, 12, 3, 0, 0, 39, 0, }, /* 346 */+ { 39, 10, 5, 0, 0, 39, 0, }, /* 347 */+ { 39, 13, 12, 0, 0, -88, 0, }, /* 348 */+ { 39, 21, 12, 0, 0, 39, 0, }, /* 349 */+ { 39, 13, 12, 0, 0, 39, 0, }, /* 350 */+ { 39, 26, 12, 0, 0, 39, 0, }, /* 351 */+ { 17, 9, 12, 0, 7264, 17, 0, }, /* 352 */+ { 17, 5, 12, 0, 3008, 17, 0, }, /* 353 */+ { 10, 21, 12, 0, 0, -49, 0, }, /* 354 */+ { 17, 6, 12, 0, 0, 17, 0, }, /* 355 */+ { 24, 7, 6, 0, 0, 24, 0, }, /* 356 */+ { 24, 7, 7, 0, 0, 24, 0, }, /* 357 */+ { 24, 7, 8, 0, 0, 24, 0, }, /* 358 */+ { 16, 7, 12, 0, 0, 16, 0, }, /* 359 */+ { 16, 12, 3, 0, 0, 16, 0, }, /* 360 */+ { 16, 21, 12, 0, 0, 16, 0, }, /* 361 */+ { 16, 15, 12, 0, 0, 16, 0, }, /* 362 */+ { 16, 26, 12, 0, 0, 16, 0, }, /* 363 */+ { 9, 9, 12, 0, 38864, 9, 0, }, /* 364 */+ { 9, 9, 12, 0, 8, 9, 0, }, /* 365 */+ { 9, 5, 12, 0, -8, 9, 0, }, /* 366 */+ { 8, 17, 12, 0, 0, 8, 0, }, /* 367 */+ { 8, 7, 12, 0, 0, 8, 0, }, /* 368 */+ { 8, 26, 12, 0, 0, 8, 0, }, /* 369 */+ { 8, 21, 12, 0, 0, 8, 0, }, /* 370 */+ { 41, 29, 12, 0, 0, 41, 0, }, /* 371 */+ { 41, 7, 12, 0, 0, 41, 0, }, /* 372 */+ { 41, 22, 12, 0, 0, 41, 0, }, /* 373 */+ { 41, 18, 12, 0, 0, 41, 0, }, /* 374 */+ { 46, 7, 12, 0, 0, 46, 0, }, /* 375 */+ { 46, 14, 12, 0, 0, 46, 0, }, /* 376 */+ { 51, 7, 12, 0, 0, 51, 0, }, /* 377 */+ { 51, 12, 3, 0, 0, 51, 0, }, /* 378 */+ { 25, 7, 12, 0, 0, 25, 0, }, /* 379 */+ { 25, 12, 3, 0, 0, 25, 0, }, /* 380 */+ { 10, 21, 12, 0, 0, -117, 0, }, /* 381 */+ { 7, 7, 12, 0, 0, 7, 0, }, /* 382 */+ { 7, 12, 3, 0, 0, 7, 0, }, /* 383 */+ { 52, 7, 12, 0, 0, 52, 0, }, /* 384 */+ { 52, 12, 3, 0, 0, 52, 0, }, /* 385 */+ { 32, 7, 12, 0, 0, 32, 0, }, /* 386 */+ { 32, 12, 3, 0, 0, 32, 0, }, /* 387 */+ { 32, 10, 5, 0, 0, 32, 0, }, /* 388 */+ { 32, 21, 12, 0, 0, 32, 0, }, /* 389 */+ { 32, 6, 12, 0, 0, 32, 0, }, /* 390 */+ { 32, 23, 12, 0, 0, 32, 0, }, /* 391 */+ { 32, 13, 12, 0, 0, 32, 0, }, /* 392 */+ { 32, 15, 12, 0, 0, 32, 0, }, /* 393 */+ { 38, 21, 12, 0, 0, 38, 0, }, /* 394 */+ { 10, 21, 12, 0, 0, -73, 0, }, /* 395 */+ { 38, 17, 12, 0, 0, 38, 0, }, /* 396 */+ { 38, 12, 3, 0, 0, 38, 0, }, /* 397 */+ { 38, 1, 2, 0, 0, 38, 0, }, /* 398 */+ { 38, 13, 12, 0, 0, 38, 0, }, /* 399 */+ { 38, 7, 12, 0, 0, 38, 0, }, /* 400 */+ { 38, 6, 12, 0, 0, 38, 0, }, /* 401 */+ { 35, 7, 12, 0, 0, 35, 0, }, /* 402 */+ { 35, 12, 3, 0, 0, 35, 0, }, /* 403 */+ { 35, 10, 5, 0, 0, 35, 0, }, /* 404 */+ { 35, 26, 12, 0, 0, 35, 0, }, /* 405 */+ { 35, 21, 12, 0, 0, 35, 0, }, /* 406 */+ { 35, 13, 12, 0, 0, 35, 0, }, /* 407 */+ { 53, 7, 12, 0, 0, 53, 0, }, /* 408 */+ { 40, 7, 12, 0, 0, 40, 0, }, /* 409 */+ { 40, 13, 12, 0, 0, 40, 0, }, /* 410 */+ { 40, 15, 12, 0, 0, 40, 0, }, /* 411 */+ { 40, 26, 12, 0, 0, 40, 0, }, /* 412 */+ { 32, 26, 12, 0, 0, 32, 0, }, /* 413 */+ { 6, 7, 12, 0, 0, 6, 0, }, /* 414 */+ { 6, 12, 3, 0, 0, 6, 0, }, /* 415 */+ { 6, 10, 5, 0, 0, 6, 0, }, /* 416 */+ { 6, 21, 12, 0, 0, 6, 0, }, /* 417 */+ { 91, 7, 12, 0, 0, 91, 0, }, /* 418 */+ { 91, 10, 5, 0, 0, 91, 0, }, /* 419 */+ { 91, 12, 3, 0, 0, 91, 0, }, /* 420 */+ { 91, 10, 12, 0, 0, 91, 0, }, /* 421 */+ { 91, 13, 12, 0, 0, 91, 0, }, /* 422 */+ { 91, 21, 12, 0, 0, 91, 0, }, /* 423 */+ { 91, 6, 12, 0, 0, 91, 0, }, /* 424 */+ { 28, 11, 3, 0, 0, 28, 0, }, /* 425 */+ { 62, 12, 3, 0, 0, 62, 0, }, /* 426 */+ { 62, 10, 5, 0, 0, 62, 0, }, /* 427 */+ { 62, 7, 12, 0, 0, 62, 0, }, /* 428 */+ { 62, 10, 3, 0, 0, 62, 0, }, /* 429 */+ { 62, 13, 12, 0, 0, 62, 0, }, /* 430 */+ { 62, 21, 12, 0, 0, 62, 0, }, /* 431 */+ { 62, 26, 12, 0, 0, 62, 0, }, /* 432 */+ { 76, 12, 3, 0, 0, 76, 0, }, /* 433 */+ { 76, 10, 5, 0, 0, 76, 0, }, /* 434 */+ { 76, 7, 12, 0, 0, 76, 0, }, /* 435 */+ { 76, 13, 12, 0, 0, 76, 0, }, /* 436 */+ { 93, 7, 12, 0, 0, 93, 0, }, /* 437 */+ { 93, 12, 3, 0, 0, 93, 0, }, /* 438 */+ { 93, 10, 5, 0, 0, 93, 0, }, /* 439 */+ { 93, 21, 12, 0, 0, 93, 0, }, /* 440 */+ { 70, 7, 12, 0, 0, 70, 0, }, /* 441 */+ { 70, 10, 5, 0, 0, 70, 0, }, /* 442 */+ { 70, 12, 3, 0, 0, 70, 0, }, /* 443 */+ { 70, 21, 12, 0, 0, 70, 0, }, /* 444 */+ { 70, 13, 12, 0, 0, 70, 0, }, /* 445 */+ { 73, 13, 12, 0, 0, 73, 0, }, /* 446 */+ { 73, 7, 12, 0, 0, 73, 0, }, /* 447 */+ { 73, 6, 12, 0, 0, 73, 0, }, /* 448 */+ { 73, 21, 12, 0, 0, 73, 0, }, /* 449 */+ { 13, 5, 12, 63, -6222, 13, 0, }, /* 450 */+ { 13, 5, 12, 67, -6221, 13, 0, }, /* 451 */+ { 13, 5, 12, 71, -6212, 13, 0, }, /* 452 */+ { 13, 5, 12, 75, -6210, 13, 0, }, /* 453 */+ { 13, 5, 12, 79, -6210, 13, 0, }, /* 454 */+ { 13, 5, 12, 79, -6211, 13, 0, }, /* 455 */+ { 13, 5, 12, 84, -6204, 13, 0, }, /* 456 */+ { 13, 5, 12, 88, -6180, 13, 0, }, /* 457 */+ { 13, 5, 12, 108, 35267, 13, 0, }, /* 458 */+ { 17, 9, 12, 0, -3008, 17, 0, }, /* 459 */+ { 76, 21, 12, 0, 0, 76, 0, }, /* 460 */+ { 28, 12, 3, 0, 0, -112, 0, }, /* 461 */+ { 28, 12, 3, 0, 0, 15, 0, }, /* 462 */+ { 10, 21, 12, 0, 0, -37, 0, }, /* 463 */+ { 28, 12, 3, 0, 0, -13, 0, }, /* 464 */+ { 28, 12, 3, 0, 0, -43, 0, }, /* 465 */+ { 28, 12, 3, 0, 0, -146, 0, }, /* 466 */+ { 10, 10, 5, 0, 0, -13, 0, }, /* 467 */+ { 10, 7, 12, 0, 0, -40, 0, }, /* 468 */+ { 10, 7, 12, 0, 0, -13, 0, }, /* 469 */+ { 10, 7, 12, 0, 0, 15, 0, }, /* 470 */+ { 10, 7, 12, 0, 0, -162, 0, }, /* 471 */+ { 10, 7, 12, 0, 0, -37, 0, }, /* 472 */+ { 28, 12, 3, 0, 0, -96, 0, }, /* 473 */+ { 10, 10, 5, 0, 0, 3, 0, }, /* 474 */+ { 28, 12, 3, 0, 0, -37, 0, }, /* 475 */+ { 10, 7, 12, 0, 0, 150, 0, }, /* 476 */+ { 13, 5, 12, 0, 0, 13, 0, }, /* 477 */+ { 13, 6, 12, 0, 0, 13, 0, }, /* 478 */+ { 34, 5, 12, 0, 35332, 34, 0, }, /* 479 */+ { 34, 5, 12, 0, 3814, 34, 0, }, /* 480 */+ { 34, 5, 12, 0, 35384, 34, 0, }, /* 481 */+ { 28, 12, 3, 0, 0, -34, 0, }, /* 482 */+ { 34, 9, 12, 92, 1, 34, 0, }, /* 483 */+ { 34, 5, 12, 92, -1, 34, 0, }, /* 484 */+ { 34, 5, 12, 92, -58, 34, 0, }, /* 485 */+ { 34, 9, 12, 0, -7615, 34, 0, }, /* 486 */+ { 20, 5, 12, 0, 8, 20, 0, }, /* 487 */+ { 20, 9, 12, 0, -8, 20, 0, }, /* 488 */+ { 20, 5, 12, 0, 74, 20, 0, }, /* 489 */+ { 20, 5, 12, 0, 86, 20, 0, }, /* 490 */+ { 20, 5, 12, 0, 100, 20, 0, }, /* 491 */+ { 20, 5, 12, 0, 128, 20, 0, }, /* 492 */+ { 20, 5, 12, 0, 112, 20, 0, }, /* 493 */+ { 20, 5, 12, 0, 126, 20, 0, }, /* 494 */+ { 20, 8, 12, 0, -8, 20, 0, }, /* 495 */+ { 20, 5, 12, 0, 9, 20, 0, }, /* 496 */+ { 20, 9, 12, 0, -74, 20, 0, }, /* 497 */+ { 20, 8, 12, 0, -9, 20, 0, }, /* 498 */+ { 20, 5, 12, 21, -7173, 20, 0, }, /* 499 */+ { 20, 9, 12, 0, -86, 20, 0, }, /* 500 */+ { 20, 9, 12, 0, -100, 20, 0, }, /* 501 */+ { 20, 9, 12, 0, -112, 20, 0, }, /* 502 */+ { 20, 9, 12, 0, -128, 20, 0, }, /* 503 */+ { 20, 9, 12, 0, -126, 20, 0, }, /* 504 */+ { 28, 1, 3, 0, 0, 28, 0, }, /* 505 */+ { 28, 1, 13, 0, 0, 28, 0, }, /* 506 */+ { 10, 27, 2, 0, 0, 10, 0, }, /* 507 */+ { 10, 28, 2, 0, 0, 10, 0, }, /* 508 */+ { 10, 29, 12, 0, 0, -70, 0, }, /* 509 */+ { 10, 21, 14, 0, 0, 10, 0, }, /* 510 */+ { 0, 2, 2, 0, 0, 0, 0, }, /* 511 */+ { 28, 12, 3, 0, 0, -100, 0, }, /* 512 */+ { 10, 9, 12, 0, 0, 10, 0, }, /* 513 */+ { 10, 5, 12, 0, 0, 10, 0, }, /* 514 */+ { 20, 9, 12, 96, -7517, 20, 0, }, /* 515 */+ { 34, 9, 12, 100, -8383, 34, 0, }, /* 516 */+ { 34, 9, 12, 104, -8262, 34, 0, }, /* 517 */+ { 34, 9, 12, 0, 28, 34, 0, }, /* 518 */+ { 10, 7, 12, 0, 0, 10, 0, }, /* 519 */+ { 10, 5, 14, 0, 0, 10, 0, }, /* 520 */+ { 34, 5, 12, 0, -28, 34, 0, }, /* 521 */+ { 34, 14, 12, 0, 16, 34, 0, }, /* 522 */+ { 34, 14, 12, 0, -16, 34, 0, }, /* 523 */+ { 34, 14, 12, 0, 0, 34, 0, }, /* 524 */+ { 10, 25, 14, 0, 0, 10, 0, }, /* 525 */+ { 10, 26, 12, 0, 26, 10, 0, }, /* 526 */+ { 10, 26, 14, 0, 26, 10, 0, }, /* 527 */+ { 10, 26, 12, 0, -26, 10, 0, }, /* 528 */+ { 5, 26, 12, 0, 0, 5, 0, }, /* 529 */+ { 18, 9, 12, 0, 48, 18, 0, }, /* 530 */+ { 18, 5, 12, 0, -48, 18, 0, }, /* 531 */+ { 34, 9, 12, 0, -10743, 34, 0, }, /* 532 */+ { 34, 9, 12, 0, -3814, 34, 0, }, /* 533 */+ { 34, 9, 12, 0, -10727, 34, 0, }, /* 534 */+ { 34, 5, 12, 0, -10795, 34, 0, }, /* 535 */+ { 34, 5, 12, 0, -10792, 34, 0, }, /* 536 */+ { 34, 9, 12, 0, -10780, 34, 0, }, /* 537 */+ { 34, 9, 12, 0, -10749, 34, 0, }, /* 538 */+ { 34, 9, 12, 0, -10783, 34, 0, }, /* 539 */+ { 34, 9, 12, 0, -10782, 34, 0, }, /* 540 */+ { 34, 9, 12, 0, -10815, 34, 0, }, /* 541 */+ { 11, 5, 12, 0, 0, 11, 0, }, /* 542 */+ { 11, 26, 12, 0, 0, 11, 0, }, /* 543 */+ { 11, 12, 3, 0, 0, 11, 0, }, /* 544 */+ { 11, 21, 12, 0, 0, 11, 0, }, /* 545 */+ { 11, 15, 12, 0, 0, 11, 0, }, /* 546 */+ { 17, 5, 12, 0, -7264, 17, 0, }, /* 547 */+ { 59, 7, 12, 0, 0, 59, 0, }, /* 548 */+ { 59, 6, 12, 0, 0, 59, 0, }, /* 549 */+ { 59, 21, 12, 0, 0, 59, 0, }, /* 550 */+ { 59, 12, 3, 0, 0, 59, 0, }, /* 551 */+ { 13, 12, 3, 0, 0, 13, 0, }, /* 552 */+ { 10, 21, 12, 0, 0, -25, 0, }, /* 553 */+ { 23, 26, 12, 0, 0, 23, 0, }, /* 554 */+ { 10, 21, 12, 0, 0, -139, 0, }, /* 555 */+ { 10, 21, 12, 0, 0, -133, 0, }, /* 556 */+ { 23, 6, 12, 0, 0, 23, 0, }, /* 557 */+ { 10, 7, 12, 0, 0, 23, 0, }, /* 558 */+ { 23, 14, 12, 0, 0, 23, 0, }, /* 559 */+ { 10, 22, 12, 0, 0, -139, 0, }, /* 560 */+ { 10, 18, 12, 0, 0, -139, 0, }, /* 561 */+ { 10, 26, 12, 0, 0, -133, 0, }, /* 562 */+ { 10, 17, 12, 0, 0, -133, 0, }, /* 563 */+ { 10, 22, 12, 0, 0, -133, 0, }, /* 564 */+ { 10, 18, 12, 0, 0, -133, 0, }, /* 565 */+ { 28, 12, 3, 0, 0, -16, 0, }, /* 566 */+ { 24, 10, 3, 0, 0, 24, 0, }, /* 567 */+ { 10, 17, 14, 0, 0, -133, 0, }, /* 568 */+ { 10, 6, 12, 0, 0, -64, 0, }, /* 569 */+ { 10, 7, 12, 0, 0, -104, 0, }, /* 570 */+ { 10, 21, 14, 0, 0, -104, 0, }, /* 571 */+ { 10, 26, 12, 0, 0, 23, 0, }, /* 572 */+ { 27, 7, 12, 0, 0, 27, 0, }, /* 573 */+ { 28, 12, 3, 0, 0, -64, 0, }, /* 574 */+ { 10, 24, 12, 0, 0, -64, 0, }, /* 575 */+ { 27, 6, 12, 0, 0, 27, 0, }, /* 576 */+ { 10, 17, 12, 0, 0, -64, 0, }, /* 577 */+ { 30, 7, 12, 0, 0, 30, 0, }, /* 578 */+ { 30, 6, 12, 0, 0, 30, 0, }, /* 579 */+ { 4, 7, 12, 0, 0, 4, 0, }, /* 580 */+ { 24, 7, 12, 0, 0, 24, 0, }, /* 581 */+ { 10, 15, 12, 0, 0, 23, 0, }, /* 582 */+ { 24, 26, 12, 0, 0, 24, 0, }, /* 583 */+ { 10, 26, 14, 0, 0, 23, 0, }, /* 584 */+ { 30, 26, 12, 0, 0, 30, 0, }, /* 585 */+ { 23, 7, 12, 0, 0, 23, 0, }, /* 586 */+ { 61, 7, 12, 0, 0, 61, 0, }, /* 587 */+ { 61, 6, 12, 0, 0, 61, 0, }, /* 588 */+ { 61, 26, 12, 0, 0, 61, 0, }, /* 589 */+ { 86, 7, 12, 0, 0, 86, 0, }, /* 590 */+ { 86, 6, 12, 0, 0, 86, 0, }, /* 591 */+ { 86, 21, 12, 0, 0, 86, 0, }, /* 592 */+ { 77, 7, 12, 0, 0, 77, 0, }, /* 593 */+ { 77, 6, 12, 0, 0, 77, 0, }, /* 594 */+ { 77, 21, 12, 0, 0, 77, 0, }, /* 595 */+ { 77, 13, 12, 0, 0, 77, 0, }, /* 596 */+ { 13, 9, 12, 108, 1, 13, 0, }, /* 597 */+ { 13, 5, 12, 108, -35267, 13, 0, }, /* 598 */+ { 13, 7, 12, 0, 0, 13, 0, }, /* 599 */+ { 13, 21, 12, 0, 0, 13, 0, }, /* 600 */+ { 79, 7, 12, 0, 0, 79, 0, }, /* 601 */+ { 79, 14, 12, 0, 0, 79, 0, }, /* 602 */+ { 79, 12, 3, 0, 0, 79, 0, }, /* 603 */+ { 79, 21, 12, 0, 0, 79, 0, }, /* 604 */+ { 10, 24, 12, 0, 0, -61, 0, }, /* 605 */+ { 34, 9, 12, 0, -35332, 34, 0, }, /* 606 */+ { 34, 9, 12, 0, -42280, 34, 0, }, /* 607 */+ { 34, 5, 12, 0, 48, 34, 0, }, /* 608 */+ { 34, 9, 12, 0, -42308, 34, 0, }, /* 609 */+ { 34, 9, 12, 0, -42319, 34, 0, }, /* 610 */+ { 34, 9, 12, 0, -42315, 34, 0, }, /* 611 */+ { 34, 9, 12, 0, -42305, 34, 0, }, /* 612 */+ { 34, 9, 12, 0, -42258, 34, 0, }, /* 613 */+ { 34, 9, 12, 0, -42282, 34, 0, }, /* 614 */+ { 34, 9, 12, 0, -42261, 34, 0, }, /* 615 */+ { 34, 9, 12, 0, 928, 34, 0, }, /* 616 */+ { 34, 9, 12, 0, -48, 34, 0, }, /* 617 */+ { 34, 9, 12, 0, -42307, 34, 0, }, /* 618 */+ { 34, 9, 12, 0, -35384, 34, 0, }, /* 619 */+ { 49, 7, 12, 0, 0, 49, 0, }, /* 620 */+ { 49, 12, 3, 0, 0, 49, 0, }, /* 621 */+ { 49, 10, 5, 0, 0, 49, 0, }, /* 622 */+ { 49, 26, 12, 0, 0, 49, 0, }, /* 623 */+ { 10, 15, 12, 0, 0, -224, 0, }, /* 624 */+ { 10, 15, 12, 0, 0, -210, 0, }, /* 625 */+ { 10, 26, 12, 0, 0, -171, 0, }, /* 626 */+ { 10, 23, 12, 0, 0, -171, 0, }, /* 627 */+ { 65, 7, 12, 0, 0, 65, 0, }, /* 628 */+ { 65, 21, 12, 0, 0, 65, 0, }, /* 629 */+ { 75, 10, 5, 0, 0, 75, 0, }, /* 630 */+ { 75, 7, 12, 0, 0, 75, 0, }, /* 631 */+ { 75, 12, 3, 0, 0, 75, 0, }, /* 632 */+ { 75, 21, 12, 0, 0, 75, 0, }, /* 633 */+ { 75, 13, 12, 0, 0, 75, 0, }, /* 634 */+ { 15, 12, 3, 0, 0, -13, 0, }, /* 635 */+ { 15, 7, 12, 0, 0, -46, 0, }, /* 636 */+ { 69, 13, 12, 0, 0, 69, 0, }, /* 637 */+ { 69, 7, 12, 0, 0, 69, 0, }, /* 638 */+ { 69, 12, 3, 0, 0, 69, 0, }, /* 639 */+ { 10, 21, 12, 0, 0, -108, 0, }, /* 640 */+ { 69, 21, 12, 0, 0, 69, 0, }, /* 641 */+ { 74, 7, 12, 0, 0, 74, 0, }, /* 642 */+ { 74, 12, 3, 0, 0, 74, 0, }, /* 643 */+ { 74, 10, 5, 0, 0, 74, 0, }, /* 644 */+ { 74, 21, 12, 0, 0, 74, 0, }, /* 645 */+ { 84, 12, 3, 0, 0, 84, 0, }, /* 646 */+ { 84, 10, 5, 0, 0, 84, 0, }, /* 647 */+ { 84, 7, 12, 0, 0, 84, 0, }, /* 648 */+ { 84, 21, 12, 0, 0, 84, 0, }, /* 649 */+ { 10, 6, 12, 0, 0, -19, 0, }, /* 650 */+ { 84, 13, 12, 0, 0, 84, 0, }, /* 651 */+ { 39, 6, 12, 0, 0, 39, 0, }, /* 652 */+ { 68, 7, 12, 0, 0, 68, 0, }, /* 653 */+ { 68, 12, 3, 0, 0, 68, 0, }, /* 654 */+ { 68, 10, 5, 0, 0, 68, 0, }, /* 655 */+ { 68, 13, 12, 0, 0, 68, 0, }, /* 656 */+ { 68, 21, 12, 0, 0, 68, 0, }, /* 657 */+ { 92, 7, 12, 0, 0, 92, 0, }, /* 658 */+ { 92, 12, 3, 0, 0, 92, 0, }, /* 659 */+ { 92, 6, 12, 0, 0, 92, 0, }, /* 660 */+ { 92, 21, 12, 0, 0, 92, 0, }, /* 661 */+ { 87, 7, 12, 0, 0, 87, 0, }, /* 662 */+ { 87, 10, 5, 0, 0, 87, 0, }, /* 663 */+ { 87, 12, 3, 0, 0, 87, 0, }, /* 664 */+ { 87, 21, 12, 0, 0, 87, 0, }, /* 665 */+ { 87, 6, 12, 0, 0, 87, 0, }, /* 666 */+ { 34, 5, 12, 0, -928, 34, 0, }, /* 667 */+ { 9, 5, 12, 0, -38864, 9, 0, }, /* 668 */+ { 87, 13, 12, 0, 0, 87, 0, }, /* 669 */+ { 24, 7, 9, 0, 0, 24, 0, }, /* 670 */+ { 24, 7, 10, 0, 0, 24, 0, }, /* 671 */+ { 0, 4, 12, 0, 0, 0, 0, }, /* 672 */+ { 0, 3, 12, 0, 0, 0, 0, }, /* 673 */+ { 26, 25, 12, 0, 0, 26, 0, }, /* 674 */+ { 1, 24, 12, 0, 0, 1, 0, }, /* 675 */+ { 1, 7, 12, 0, 0, -10, 0, }, /* 676 */+ { 1, 26, 12, 0, 0, -10, 0, }, /* 677 */+ { 10, 6, 3, 0, 0, -64, 0, }, /* 678 */+ { 36, 7, 12, 0, 0, 36, 0, }, /* 679 */+ { 10, 21, 12, 0, 0, -22, 0, }, /* 680 */+ { 10, 15, 12, 0, 0, -92, 0, }, /* 681 */+ { 10, 26, 12, 0, 0, -22, 0, }, /* 682 */+ { 20, 14, 12, 0, 0, 20, 0, }, /* 683 */+ { 20, 15, 12, 0, 0, 20, 0, }, /* 684 */+ { 20, 26, 12, 0, 0, 20, 0, }, /* 685 */+ { 71, 7, 12, 0, 0, 71, 0, }, /* 686 */+ { 67, 7, 12, 0, 0, 67, 0, }, /* 687 */+ { 28, 12, 3, 0, 0, -1, 0, }, /* 688 */+ { 10, 15, 12, 0, 0, -1, 0, }, /* 689 */+ { 42, 7, 12, 0, 0, 42, 0, }, /* 690 */+ { 42, 15, 12, 0, 0, 42, 0, }, /* 691 */+ { 19, 7, 12, 0, 0, 19, 0, }, /* 692 */+ { 19, 14, 12, 0, 0, 19, 0, }, /* 693 */+ { 118, 7, 12, 0, 0, 118, 0, }, /* 694 */+ { 118, 12, 3, 0, 0, 118, 0, }, /* 695 */+ { 60, 7, 12, 0, 0, 60, 0, }, /* 696 */+ { 60, 21, 12, 0, 0, 60, 0, }, /* 697 */+ { 43, 7, 12, 0, 0, 43, 0, }, /* 698 */+ { 43, 21, 12, 0, 0, 43, 0, }, /* 699 */+ { 43, 14, 12, 0, 0, 43, 0, }, /* 700 */+ { 14, 9, 12, 0, 40, 14, 0, }, /* 701 */+ { 14, 5, 12, 0, -40, 14, 0, }, /* 702 */+ { 47, 7, 12, 0, 0, 47, 0, }, /* 703 */+ { 45, 7, 12, 0, 0, 45, 0, }, /* 704 */+ { 45, 13, 12, 0, 0, 45, 0, }, /* 705 */+ { 136, 9, 12, 0, 40, 136, 0, }, /* 706 */+ { 136, 5, 12, 0, -40, 136, 0, }, /* 707 */+ { 106, 7, 12, 0, 0, 106, 0, }, /* 708 */+ { 104, 7, 12, 0, 0, 104, 0, }, /* 709 */+ { 104, 21, 12, 0, 0, 104, 0, }, /* 710 */+ { 110, 7, 12, 0, 0, 110, 0, }, /* 711 */+ { 12, 7, 12, 0, 0, 12, 0, }, /* 712 */+ { 81, 7, 12, 0, 0, 81, 0, }, /* 713 */+ { 81, 21, 12, 0, 0, 81, 0, }, /* 714 */+ { 81, 15, 12, 0, 0, 81, 0, }, /* 715 */+ { 120, 7, 12, 0, 0, 120, 0, }, /* 716 */+ { 120, 26, 12, 0, 0, 120, 0, }, /* 717 */+ { 120, 15, 12, 0, 0, 120, 0, }, /* 718 */+ { 116, 7, 12, 0, 0, 116, 0, }, /* 719 */+ { 116, 15, 12, 0, 0, 116, 0, }, /* 720 */+ { 128, 7, 12, 0, 0, 128, 0, }, /* 721 */+ { 128, 15, 12, 0, 0, 128, 0, }, /* 722 */+ { 66, 7, 12, 0, 0, 66, 0, }, /* 723 */+ { 66, 15, 12, 0, 0, 66, 0, }, /* 724 */+ { 66, 21, 12, 0, 0, 66, 0, }, /* 725 */+ { 72, 7, 12, 0, 0, 72, 0, }, /* 726 */+ { 72, 21, 12, 0, 0, 72, 0, }, /* 727 */+ { 98, 7, 12, 0, 0, 98, 0, }, /* 728 */+ { 97, 7, 12, 0, 0, 97, 0, }, /* 729 */+ { 97, 15, 12, 0, 0, 97, 0, }, /* 730 */+ { 31, 7, 12, 0, 0, 31, 0, }, /* 731 */+ { 31, 12, 3, 0, 0, 31, 0, }, /* 732 */+ { 31, 15, 12, 0, 0, 31, 0, }, /* 733 */+ { 31, 21, 12, 0, 0, 31, 0, }, /* 734 */+ { 88, 7, 12, 0, 0, 88, 0, }, /* 735 */+ { 88, 15, 12, 0, 0, 88, 0, }, /* 736 */+ { 88, 21, 12, 0, 0, 88, 0, }, /* 737 */+ { 117, 7, 12, 0, 0, 117, 0, }, /* 738 */+ { 117, 15, 12, 0, 0, 117, 0, }, /* 739 */+ { 112, 7, 12, 0, 0, 112, 0, }, /* 740 */+ { 112, 26, 12, 0, 0, 112, 0, }, /* 741 */+ { 112, 12, 3, 0, 0, 112, 0, }, /* 742 */+ { 112, 15, 12, 0, 0, 112, 0, }, /* 743 */+ { 112, 21, 12, 0, 0, 112, 0, }, /* 744 */+ { 78, 7, 12, 0, 0, 78, 0, }, /* 745 */+ { 78, 21, 12, 0, 0, 78, 0, }, /* 746 */+ { 83, 7, 12, 0, 0, 83, 0, }, /* 747 */+ { 83, 15, 12, 0, 0, 83, 0, }, /* 748 */+ { 82, 7, 12, 0, 0, 82, 0, }, /* 749 */+ { 82, 15, 12, 0, 0, 82, 0, }, /* 750 */+ { 121, 7, 12, 0, 0, 121, 0, }, /* 751 */+ { 121, 21, 12, 0, 0, 121, 0, }, /* 752 */+ { 121, 15, 12, 0, 0, 121, 0, }, /* 753 */+ { 89, 7, 12, 0, 0, 89, 0, }, /* 754 */+ { 130, 9, 12, 0, 64, 130, 0, }, /* 755 */+ { 130, 5, 12, 0, -64, 130, 0, }, /* 756 */+ { 130, 15, 12, 0, 0, 130, 0, }, /* 757 */+ { 144, 7, 12, 0, 0, 144, 0, }, /* 758 */+ { 144, 12, 3, 0, 0, 144, 0, }, /* 759 */+ { 144, 13, 12, 0, 0, 144, 0, }, /* 760 */+ { 1, 15, 12, 0, 0, 1, 0, }, /* 761 */+ { 156, 7, 12, 0, 0, 156, 0, }, /* 762 */+ { 156, 12, 3, 0, 0, 156, 0, }, /* 763 */+ { 156, 17, 12, 0, 0, 156, 0, }, /* 764 */+ { 147, 7, 12, 0, 0, 147, 0, }, /* 765 */+ { 147, 15, 12, 0, 0, 147, 0, }, /* 766 */+ { 148, 7, 12, 0, 0, 148, 0, }, /* 767 */+ { 148, 12, 3, 0, 0, 148, 0, }, /* 768 */+ { 148, 15, 12, 0, 0, 148, 0, }, /* 769 */+ { 148, 21, 12, 0, 0, 148, 0, }, /* 770 */+ { 153, 7, 12, 0, 0, 153, 0, }, /* 771 */+ { 153, 15, 12, 0, 0, 153, 0, }, /* 772 */+ { 149, 7, 12, 0, 0, 149, 0, }, /* 773 */+ { 94, 10, 5, 0, 0, 94, 0, }, /* 774 */+ { 94, 12, 3, 0, 0, 94, 0, }, /* 775 */+ { 94, 7, 12, 0, 0, 94, 0, }, /* 776 */+ { 94, 21, 12, 0, 0, 94, 0, }, /* 777 */+ { 94, 15, 12, 0, 0, 94, 0, }, /* 778 */+ { 94, 13, 12, 0, 0, 94, 0, }, /* 779 */+ { 85, 12, 3, 0, 0, 85, 0, }, /* 780 */+ { 85, 10, 5, 0, 0, 85, 0, }, /* 781 */+ { 85, 7, 12, 0, 0, 85, 0, }, /* 782 */+ { 85, 21, 12, 0, 0, 85, 0, }, /* 783 */+ { 85, 1, 4, 0, 0, 85, 0, }, /* 784 */+ { 101, 7, 12, 0, 0, 101, 0, }, /* 785 */+ { 101, 13, 12, 0, 0, 101, 0, }, /* 786 */+ { 96, 12, 3, 0, 0, 96, 0, }, /* 787 */+ { 96, 7, 12, 0, 0, 96, 0, }, /* 788 */+ { 96, 10, 5, 0, 0, 96, 0, }, /* 789 */+ { 96, 13, 12, 0, 0, 96, 0, }, /* 790 */+ { 96, 21, 12, 0, 0, 96, 0, }, /* 791 */+ { 111, 7, 12, 0, 0, 111, 0, }, /* 792 */+ { 111, 12, 3, 0, 0, 111, 0, }, /* 793 */+ { 111, 21, 12, 0, 0, 111, 0, }, /* 794 */+ { 100, 12, 3, 0, 0, 100, 0, }, /* 795 */+ { 100, 10, 5, 0, 0, 100, 0, }, /* 796 */+ { 100, 7, 12, 0, 0, 100, 0, }, /* 797 */+ { 100, 7, 4, 0, 0, 100, 0, }, /* 798 */+ { 100, 21, 12, 0, 0, 100, 0, }, /* 799 */+ { 100, 13, 12, 0, 0, 100, 0, }, /* 800 */+ { 48, 15, 12, 0, 0, 48, 0, }, /* 801 */+ { 108, 7, 12, 0, 0, 108, 0, }, /* 802 */+ { 108, 10, 5, 0, 0, 108, 0, }, /* 803 */+ { 108, 12, 3, 0, 0, 108, 0, }, /* 804 */+ { 108, 21, 12, 0, 0, 108, 0, }, /* 805 */+ { 129, 7, 12, 0, 0, 129, 0, }, /* 806 */+ { 129, 21, 12, 0, 0, 129, 0, }, /* 807 */+ { 109, 7, 12, 0, 0, 109, 0, }, /* 808 */+ { 109, 12, 3, 0, 0, 109, 0, }, /* 809 */+ { 109, 10, 5, 0, 0, 109, 0, }, /* 810 */+ { 109, 13, 12, 0, 0, 109, 0, }, /* 811 */+ { 107, 12, 3, 0, 0, 107, 0, }, /* 812 */+ { 107, 12, 3, 0, 0, -52, 0, }, /* 813 */+ { 107, 10, 5, 0, 0, 107, 0, }, /* 814 */+ { 107, 10, 5, 0, 0, -52, 0, }, /* 815 */+ { 107, 7, 12, 0, 0, 107, 0, }, /* 816 */+ { 28, 12, 3, 0, 0, -52, 0, }, /* 817 */+ { 107, 10, 3, 0, 0, 107, 0, }, /* 818 */+ { 135, 7, 12, 0, 0, 135, 0, }, /* 819 */+ { 135, 10, 5, 0, 0, 135, 0, }, /* 820 */+ { 135, 12, 3, 0, 0, 135, 0, }, /* 821 */+ { 135, 21, 12, 0, 0, 135, 0, }, /* 822 */+ { 135, 13, 12, 0, 0, 135, 0, }, /* 823 */+ { 124, 7, 12, 0, 0, 124, 0, }, /* 824 */+ { 124, 10, 3, 0, 0, 124, 0, }, /* 825 */+ { 124, 10, 5, 0, 0, 124, 0, }, /* 826 */+ { 124, 12, 3, 0, 0, 124, 0, }, /* 827 */+ { 124, 21, 12, 0, 0, 124, 0, }, /* 828 */+ { 124, 13, 12, 0, 0, 124, 0, }, /* 829 */+ { 123, 7, 12, 0, 0, 123, 0, }, /* 830 */+ { 123, 10, 3, 0, 0, 123, 0, }, /* 831 */+ { 123, 10, 5, 0, 0, 123, 0, }, /* 832 */+ { 123, 12, 3, 0, 0, 123, 0, }, /* 833 */+ { 123, 21, 12, 0, 0, 123, 0, }, /* 834 */+ { 114, 7, 12, 0, 0, 114, 0, }, /* 835 */+ { 114, 10, 5, 0, 0, 114, 0, }, /* 836 */+ { 114, 12, 3, 0, 0, 114, 0, }, /* 837 */+ { 114, 21, 12, 0, 0, 114, 0, }, /* 838 */+ { 114, 13, 12, 0, 0, 114, 0, }, /* 839 */+ { 102, 7, 12, 0, 0, 102, 0, }, /* 840 */+ { 102, 12, 3, 0, 0, 102, 0, }, /* 841 */+ { 102, 10, 5, 0, 0, 102, 0, }, /* 842 */+ { 102, 13, 12, 0, 0, 102, 0, }, /* 843 */+ { 126, 7, 12, 0, 0, 126, 0, }, /* 844 */+ { 126, 12, 3, 0, 0, 126, 0, }, /* 845 */+ { 126, 10, 5, 0, 0, 126, 0, }, /* 846 */+ { 126, 13, 12, 0, 0, 126, 0, }, /* 847 */+ { 126, 15, 12, 0, 0, 126, 0, }, /* 848 */+ { 126, 21, 12, 0, 0, 126, 0, }, /* 849 */+ { 126, 26, 12, 0, 0, 126, 0, }, /* 850 */+ { 142, 7, 12, 0, 0, 142, 0, }, /* 851 */+ { 142, 10, 5, 0, 0, 142, 0, }, /* 852 */+ { 142, 12, 3, 0, 0, 142, 0, }, /* 853 */+ { 142, 21, 12, 0, 0, 142, 0, }, /* 854 */+ { 125, 9, 12, 0, 32, 125, 0, }, /* 855 */+ { 125, 5, 12, 0, -32, 125, 0, }, /* 856 */+ { 125, 13, 12, 0, 0, 125, 0, }, /* 857 */+ { 125, 15, 12, 0, 0, 125, 0, }, /* 858 */+ { 125, 7, 12, 0, 0, 125, 0, }, /* 859 */+ { 154, 7, 12, 0, 0, 154, 0, }, /* 860 */+ { 154, 10, 3, 0, 0, 154, 0, }, /* 861 */+ { 154, 10, 5, 0, 0, 154, 0, }, /* 862 */+ { 154, 12, 3, 0, 0, 154, 0, }, /* 863 */+ { 154, 7, 4, 0, 0, 154, 0, }, /* 864 */+ { 154, 21, 12, 0, 0, 154, 0, }, /* 865 */+ { 154, 13, 12, 0, 0, 154, 0, }, /* 866 */+ { 150, 7, 12, 0, 0, 150, 0, }, /* 867 */+ { 150, 10, 5, 0, 0, 150, 0, }, /* 868 */+ { 150, 12, 3, 0, 0, 150, 0, }, /* 869 */+ { 150, 21, 12, 0, 0, 150, 0, }, /* 870 */+ { 141, 7, 12, 0, 0, 141, 0, }, /* 871 */+ { 141, 12, 3, 0, 0, 141, 0, }, /* 872 */+ { 141, 10, 5, 0, 0, 141, 0, }, /* 873 */+ { 141, 7, 4, 0, 0, 141, 0, }, /* 874 */+ { 141, 21, 12, 0, 0, 141, 0, }, /* 875 */+ { 140, 7, 12, 0, 0, 140, 0, }, /* 876 */+ { 140, 12, 3, 0, 0, 140, 0, }, /* 877 */+ { 140, 10, 5, 0, 0, 140, 0, }, /* 878 */+ { 140, 7, 4, 0, 0, 140, 0, }, /* 879 */+ { 140, 21, 12, 0, 0, 140, 0, }, /* 880 */+ { 122, 7, 12, 0, 0, 122, 0, }, /* 881 */+ { 133, 7, 12, 0, 0, 133, 0, }, /* 882 */+ { 133, 10, 5, 0, 0, 133, 0, }, /* 883 */+ { 133, 12, 3, 0, 0, 133, 0, }, /* 884 */+ { 133, 21, 12, 0, 0, 133, 0, }, /* 885 */+ { 133, 13, 12, 0, 0, 133, 0, }, /* 886 */+ { 133, 15, 12, 0, 0, 133, 0, }, /* 887 */+ { 134, 21, 12, 0, 0, 134, 0, }, /* 888 */+ { 134, 7, 12, 0, 0, 134, 0, }, /* 889 */+ { 134, 12, 3, 0, 0, 134, 0, }, /* 890 */+ { 134, 10, 5, 0, 0, 134, 0, }, /* 891 */+ { 138, 7, 12, 0, 0, 138, 0, }, /* 892 */+ { 138, 12, 3, 0, 0, 138, 0, }, /* 893 */+ { 138, 7, 4, 0, 0, 138, 0, }, /* 894 */+ { 138, 13, 12, 0, 0, 138, 0, }, /* 895 */+ { 143, 7, 12, 0, 0, 143, 0, }, /* 896 */+ { 143, 10, 5, 0, 0, 143, 0, }, /* 897 */+ { 143, 12, 3, 0, 0, 143, 0, }, /* 898 */+ { 143, 13, 12, 0, 0, 143, 0, }, /* 899 */+ { 145, 7, 12, 0, 0, 145, 0, }, /* 900 */+ { 145, 12, 3, 0, 0, 145, 0, }, /* 901 */+ { 145, 10, 5, 0, 0, 145, 0, }, /* 902 */+ { 145, 21, 12, 0, 0, 145, 0, }, /* 903 */+ { 54, 15, 12, 0, 0, 54, 0, }, /* 904 */+ { 54, 21, 12, 0, 0, 54, 0, }, /* 905 */+ { 63, 7, 12, 0, 0, 63, 0, }, /* 906 */+ { 63, 14, 12, 0, 0, 63, 0, }, /* 907 */+ { 63, 21, 12, 0, 0, 63, 0, }, /* 908 */+ { 80, 7, 12, 0, 0, 80, 0, }, /* 909 */+ { 80, 1, 2, 0, 0, 80, 0, }, /* 910 */+ { 127, 7, 12, 0, 0, 127, 0, }, /* 911 */+ { 115, 7, 12, 0, 0, 115, 0, }, /* 912 */+ { 115, 13, 12, 0, 0, 115, 0, }, /* 913 */+ { 115, 21, 12, 0, 0, 115, 0, }, /* 914 */+ { 103, 7, 12, 0, 0, 103, 0, }, /* 915 */+ { 103, 12, 3, 0, 0, 103, 0, }, /* 916 */+ { 103, 21, 12, 0, 0, 103, 0, }, /* 917 */+ { 119, 7, 12, 0, 0, 119, 0, }, /* 918 */+ { 119, 12, 3, 0, 0, 119, 0, }, /* 919 */+ { 119, 21, 12, 0, 0, 119, 0, }, /* 920 */+ { 119, 26, 12, 0, 0, 119, 0, }, /* 921 */+ { 119, 6, 12, 0, 0, 119, 0, }, /* 922 */+ { 119, 13, 12, 0, 0, 119, 0, }, /* 923 */+ { 119, 15, 12, 0, 0, 119, 0, }, /* 924 */+ { 146, 9, 12, 0, 32, 146, 0, }, /* 925 */+ { 146, 5, 12, 0, -32, 146, 0, }, /* 926 */+ { 146, 15, 12, 0, 0, 146, 0, }, /* 927 */+ { 146, 21, 12, 0, 0, 146, 0, }, /* 928 */+ { 99, 7, 12, 0, 0, 99, 0, }, /* 929 */+ { 99, 12, 3, 0, 0, 99, 0, }, /* 930 */+ { 99, 10, 5, 0, 0, 99, 0, }, /* 931 */+ { 99, 6, 12, 0, 0, 99, 0, }, /* 932 */+ { 137, 6, 12, 0, 0, 137, 0, }, /* 933 */+ { 139, 6, 12, 0, 0, 139, 0, }, /* 934 */+ { 155, 12, 3, 0, 0, 155, 0, }, /* 935 */+ { 23, 10, 5, 0, 0, 23, 0, }, /* 936 */+ { 137, 7, 12, 0, 0, 137, 0, }, /* 937 */+ { 155, 7, 12, 0, 0, 155, 0, }, /* 938 */+ { 139, 7, 12, 0, 0, 139, 0, }, /* 939 */+ { 105, 7, 12, 0, 0, 105, 0, }, /* 940 */+ { 105, 26, 12, 0, 0, 105, 0, }, /* 941 */+ { 105, 12, 3, 0, 0, 105, 0, }, /* 942 */+ { 105, 21, 12, 0, 0, 105, 0, }, /* 943 */+ { 10, 1, 2, 0, 0, 105, 0, }, /* 944 */+ { 10, 10, 3, 0, 0, 10, 0, }, /* 945 */+ { 10, 10, 5, 0, 0, 10, 0, }, /* 946 */+ { 20, 12, 3, 0, 0, 20, 0, }, /* 947 */+ { 131, 26, 12, 0, 0, 131, 0, }, /* 948 */+ { 131, 12, 3, 0, 0, 131, 0, }, /* 949 */+ { 131, 21, 12, 0, 0, 131, 0, }, /* 950 */+ { 18, 12, 3, 0, 0, 18, 0, }, /* 951 */+ { 151, 7, 12, 0, 0, 151, 0, }, /* 952 */+ { 151, 12, 3, 0, 0, 151, 0, }, /* 953 */+ { 151, 6, 12, 0, 0, 151, 0, }, /* 954 */+ { 151, 13, 12, 0, 0, 151, 0, }, /* 955 */+ { 151, 26, 12, 0, 0, 151, 0, }, /* 956 */+ { 152, 7, 12, 0, 0, 152, 0, }, /* 957 */+ { 152, 12, 3, 0, 0, 152, 0, }, /* 958 */+ { 152, 13, 12, 0, 0, 152, 0, }, /* 959 */+ { 152, 23, 12, 0, 0, 152, 0, }, /* 960 */+ { 113, 7, 12, 0, 0, 113, 0, }, /* 961 */+ { 113, 15, 12, 0, 0, 113, 0, }, /* 962 */+ { 113, 12, 3, 0, 0, 113, 0, }, /* 963 */+ { 132, 9, 12, 0, 34, 132, 0, }, /* 964 */+ { 132, 5, 12, 0, -34, 132, 0, }, /* 965 */+ { 132, 12, 3, 0, 0, 132, 0, }, /* 966 */+ { 132, 6, 12, 0, 0, 132, 0, }, /* 967 */+ { 132, 13, 12, 0, 0, 132, 0, }, /* 968 */+ { 132, 21, 12, 0, 0, 132, 0, }, /* 969 */+ { 0, 2, 14, 0, 0, 0, 0, }, /* 970 */+ { 10, 26, 11, 0, 0, 10, 0, }, /* 971 */+ { 27, 26, 12, 0, 0, 27, 0, }, /* 972 */+ { 10, 24, 3, 0, 0, 10, 0, }, /* 973 */+ { 10, 1, 3, 0, 0, 10, 0, }, /* 974 */+};++const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* U+0000 */+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* U+0800 */+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 42, 43, 44, 45, /* U+1000 */+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, /* U+1800 */+ 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, /* U+2000 */+ 77, 77, 78, 79, 66, 66, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, /* U+2800 */+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 98, 98, 98, 98, 98, 98, 98, /* U+3000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+3800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+4000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 98, 98, 98, 98, /* U+4800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+5000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+5800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+6000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+6800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+7000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+7800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+8000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+8800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+9000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,100, /* U+9800 */+101,102,102,102,102,102,102,102,102,103,104,104,105,106,107,108, /* U+A000 */+109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,117, /* U+A800 */+118,119,120,121,122,123,117,118,119,120,121,122,123,117,118,119, /* U+B000 */+120,121,122,123,117,118,119,120,121,122,123,117,118,119,120,121, /* U+B800 */+122,123,117,118,119,120,121,122,123,117,118,119,120,121,122,123, /* U+C000 */+117,118,119,120,121,122,123,117,118,119,120,121,122,123,117,118, /* U+C800 */+119,120,121,122,123,117,118,119,120,121,122,123,117,118,119,124, /* U+D000 */+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+D800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+E000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+E800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F000 */+126,126, 98, 98,127,128,129,130,131,131,132,133,134,135,136,137, /* U+F800 */+138,139,140,141,142,143,144,145,146,147,148,142,149,149,150,142, /* U+10000 */+151,152,153,154,155,156,157,158,159,160,161,142,162,163,164,165, /* U+10800 */+166,167,168,169,170,171,172,142,173,174,142,175,176,177,178,142, /* U+11000 */+179,180,181,182,183,184,142,142,185,186,187,188,142,189,142,190, /* U+11800 */+191,191,191,191,191,191,191,192,193,191,194,142,142,142,142,142, /* U+12000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+12800 */+195,195,195,195,195,195,195,195,196,142,142,142,142,142,142,142, /* U+13000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+13800 */+142,142,142,142,142,142,142,142,197,197,197,197,198,142,142,142, /* U+14000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+14800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+15000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+15800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+16000 */+199,199,199,199,200,201,202,203,142,142,142,142,204,205,206,207, /* U+16800 */+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, /* U+17000 */+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, /* U+17800 */+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,209, /* U+18000 */+208,208,208,208,208,208,210,210,210,211,212,142,142,142,142,142, /* U+18800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+19000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+19800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1A000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1A800 */+213,214,215,216,216,217,142,142,142,142,142,142,142,142,142,142, /* U+1B000 */+142,142,142,142,142,142,142,142,218,219,142,142,142,142,142,142, /* U+1B800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1C000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1C800 */+ 71,220,221,222,223,224,225,142,226,227,228,229,230,231,232,233, /* U+1D000 */+234,234,234,234,235,236,142,142,142,142,142,142,142,142,142,142, /* U+1D800 */+237,142,238,142,142,239,142,142,142,142,142,142,142,142,142,142, /* U+1E000 */+240,241,242,142,142,142,142,142,243,244,245,142,246,247,142,142, /* U+1E800 */+248,249,250,251,252,253,254,255,254,254,256,254,257,258,259,260, /* U+1F000 */+261,262,263,264,265,266, 71,267,253,253,253,253,253,253,253,268, /* U+1F800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+20000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+20800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+21000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+21800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+22000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+22800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+23000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+23800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+24000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+24800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+25000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+25800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+26000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+26800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+27000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+27800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+28000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+28800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+29000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+29800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,269, 98, 98, /* U+2A000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2A800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,270, 98, /* U+2B000 */+271, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2B800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2C000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,272, 98, 98, /* U+2C800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2D000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2D800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2E000 */+ 98, 98, 98, 98, 98, 98, 98,273,142,142,142,142,142,142,142,142, /* U+2E800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+2F000 */+ 98, 98, 98, 98,274,142,142,142,142,142,142,142,142,142,142,142, /* U+2F800 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+30000 */+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+30800 */+ 98, 98, 98, 98, 98, 98,275,142,142,142,142,142,142,142,142,142, /* U+31000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+31800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+32000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+32800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+33000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+33800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+34000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+34800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+35000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+35800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+36000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+36800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+37000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+37800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+38000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+38800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+39000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+39800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3A000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3A800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3B000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3B800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3C000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3C800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3D000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3D800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3E000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3E800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3F000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+3F800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+40000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+40800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+41000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+41800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+42000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+42800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+43000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+43800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+44000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+44800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+45000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+45800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+46000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+46800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+47000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+47800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+48000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+48800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+49000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+49800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4A000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4A800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4B000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4B800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4C000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4C800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4D000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4D800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4E000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4E800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4F000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+4F800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+50000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+50800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+51000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+51800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+52000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+52800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+53000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+53800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+54000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+54800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+55000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+55800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+56000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+56800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+57000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+57800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+58000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+58800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+59000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+59800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5A000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5A800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5B000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5B800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5C000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5C800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5D000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5D800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5E000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5E800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5F000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+5F800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+60000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+60800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+61000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+61800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+62000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+62800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+63000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+63800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+64000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+64800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+65000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+65800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+66000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+66800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+67000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+67800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+68000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+68800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+69000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+69800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6A000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6A800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6B000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6B800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6C000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6C800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6D000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6D800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6E000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6E800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6F000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+6F800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+70000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+70800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+71000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+71800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+72000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+72800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+73000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+73800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+74000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+74800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+75000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+75800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+76000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+76800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+77000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+77800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+78000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+78800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+79000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+79800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7A000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7A800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7B000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7B800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7C000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7C800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7D000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7D800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7E000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7E800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7F000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+7F800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+80000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+80800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+81000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+81800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+82000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+82800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+83000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+83800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+84000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+84800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+85000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+85800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+86000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+86800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+87000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+87800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+88000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+88800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+89000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+89800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8A000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8A800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8B000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8B800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8C000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8C800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8D000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8D800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8E000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8E800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8F000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+8F800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+90000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+90800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+91000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+91800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+92000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+92800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+93000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+93800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+94000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+94800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+95000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+95800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+96000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+96800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+97000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+97800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+98000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+98800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+99000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+99800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9A000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9A800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9B000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9B800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9C000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9C800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9D000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9D800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9E000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9E800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9F000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+9F800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A0000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A0800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A1000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A1800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A2000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A2800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A3000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A3800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A4000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A4800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A5000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A5800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A6000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A6800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A7000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A7800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A8000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A8800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A9000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+A9800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AA000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AA800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AB000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AB800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AC000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AC800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AD000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AD800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AE000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AE800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AF000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+AF800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B0000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B0800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B1000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B1800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B2000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B2800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B3000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B3800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B4000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B4800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B5000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B5800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B6000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B6800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B7000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B7800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B8000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B8800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B9000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+B9800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BA000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BA800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BB000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BB800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BC000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BC800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BD000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BD800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BE000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BE800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BF000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+BF800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C0000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C0800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C1000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C1800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C2000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C2800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C3000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C3800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C4000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C4800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C5000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C5800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C6000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C6800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C7000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C7800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C8000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C8800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C9000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+C9800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CA000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CA800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CB000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CB800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CC000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CC800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CD000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CD800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CE000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CE800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CF000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+CF800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D0000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D0800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D1000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D1800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D2000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D2800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D3000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D3800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D4000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D4800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D5000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D5800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D6000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D6800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D7000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D7800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D8000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D8800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D9000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+D9800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DA000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DA800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DB000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DB800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DC000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DC800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DD000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DD800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DE000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DE800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DF000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DF800 */+276,277,278,279,277,277,277,277,277,277,277,277,277,277,277,277, /* U+E0000 */+277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, /* U+E0800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E1000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E1800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E2000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E2800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E3000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E3800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E4000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E4800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E5000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E5800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E6000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E6800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E7000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E7800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E8000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E8800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E9000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E9800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+EA000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+EA800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+EB000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+EB800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+EC000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+EC800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+ED000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+ED800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+EE000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+EE800 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+EF000 */+142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+EF800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F0000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F0800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F1000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F1800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F2000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F2800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F3000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F3800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F4000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F4800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F5000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F5800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F6000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F6800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F7000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F7800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F8000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F8800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F9000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F9800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FA000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FA800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FB000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FB800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FC000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FC800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FD000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FD800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FE000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FE800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FF000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,280, /* U+FF800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+100000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+100800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+101000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+101800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+102000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+102800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+103000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+103800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+104000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+104800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+105000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+105800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+106000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+106800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+107000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+107800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+108000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+108800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+109000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+109800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10A000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10A800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10B000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10B800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10C000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10C800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10D000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10D800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10E000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10E800 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10F000 */+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,280, /* U+10F800 */+};++const uint16_t PRIV(ucd_stage2)[] = { /* 71936 bytes, block = 128 */+/* block 0 */+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 4, 5, 5, 5, 6, 5, 5, 5, 7, 8, 5, 9, 5, 10, 5, 5,+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 5, 5, 9, 9, 9, 5,+ 5, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 12, 12, 12, 12,+ 12, 12, 12, 14, 12, 12, 12, 12, 12, 12, 12, 7, 5, 8, 15, 16,+ 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 17, 17, 17, 17,+ 17, 17, 17, 19, 17, 17, 17, 17, 17, 17, 17, 7, 9, 8, 9, 1,++/* block 1 */+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 4, 5, 6, 6, 6, 6, 20, 5, 15, 21, 22, 23, 9, 24, 21, 15,+ 20, 9, 25, 25, 15, 26, 5, 5, 15, 25, 22, 27, 25, 25, 25, 5,+ 12, 12, 12, 12, 12, 28, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,+ 12, 12, 12, 12, 12, 12, 12, 9, 12, 12, 12, 12, 12, 12, 12, 29,+ 17, 17, 17, 17, 17, 30, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,+ 17, 17, 17, 17, 17, 17, 17, 9, 17, 17, 17, 17, 17, 17, 17, 31,++/* block 2 */+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 34, 35, 32, 33, 32, 33, 32, 33, 35, 32, 33, 32, 33, 32, 33, 32,+ 33, 32, 33, 32, 33, 32, 33, 32, 33, 35, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 36, 32, 33, 32, 33, 32, 33, 37,++/* block 3 */+ 38, 39, 32, 33, 32, 33, 40, 32, 33, 41, 41, 32, 33, 35, 42, 43,+ 44, 32, 33, 41, 45, 46, 47, 48, 32, 33, 49, 35, 47, 50, 51, 52,+ 32, 33, 32, 33, 32, 33, 53, 32, 33, 53, 35, 35, 32, 33, 53, 32,+ 33, 54, 54, 32, 33, 32, 33, 55, 32, 33, 35, 22, 32, 33, 35, 56,+ 22, 22, 22, 22, 57, 58, 59, 60, 61, 62, 63, 64, 65, 32, 33, 32,+ 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 66, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 35, 67, 68, 69, 32, 33, 70, 71, 32, 33, 32, 33, 32, 33, 32, 33,++/* block 4 */+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 72, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 35, 35, 35, 35, 35, 35, 73, 32, 33, 74, 75, 76,+ 76, 32, 33, 77, 78, 79, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 80, 81, 82, 83, 84, 35, 85, 85, 35, 86, 35, 87, 88, 35, 35, 35,+ 85, 89, 35, 90, 35, 91, 92, 35, 93, 94, 92, 95, 96, 35, 35, 94,+ 35, 97, 98, 35, 35, 99, 35, 35, 35, 35, 35, 35, 35,100, 35, 35,++/* block 5 */+101, 35,102,101, 35, 35, 35,103,101,104,105,105,106, 35, 35, 35,+ 35, 35,107, 35, 22, 35, 35, 35, 35, 35, 35, 35, 35,108,109, 35,+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,+110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,+111,111, 15, 15, 15, 15,111,111,111,111,111,111,111,111,111,111,+111,111, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,+110,110,110,110,110, 15, 15, 15, 15, 15,112,112,111, 15,111, 15,+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,++/* block 6 */+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,114,113,113,115,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,116,116,116,116,116,116,116,116,116,116,116,116,116,+117,118,117,118,111,119,117,118,120,120,121,122,122,122, 5,123,++/* block 7 */+120,120,120,120,119, 15,124, 5,125,125,125,120,126,120,127,127,+128,129,130,129,129,131,129,129,132,133,134,129,135,129,129,129,+136,137,120,138,129,129,139,129,129,140,129,129,141,142,142,142,+128,143,144,143,143,145,143,143,146,147,148,143,149,143,143,143,+150,151,152,153,143,143,154,143,143,155,143,143,156,157,157,158,+159,160,161,161,161,162,163,164,117,118,117,118,117,118,117,118,+117,118,165,166,165,166,165,166,165,166,165,166,165,166,165,166,+167,168,169,170,171,172,173,117,118,174,117,118,128,175,175,175,++/* block 8 */+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,+177,177,178,177,179,177,177,177,177,177,177,177,177,177,180,177,+177,181,182,177,177,177,177,177,177,177,183,177,177,177,177,177,+184,184,185,184,186,184,184,184,184,184,184,184,184,184,187,184,+184,188,189,184,184,184,184,184,184,184,190,184,184,184,184,184,+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,+192,193,194,195,192,193,192,193,192,193,192,193,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,++/* block 9 */+192,193,196,197,198,199,199,198,200,200,192,193,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,+201,192,193,192,193,192,193,192,193,192,193,192,193,192,193,202,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,++/* block 10 */+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,+120,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,+203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,+203,203,203,203,203,203,203,120,120,204,205,205,205,205,205,205,+206,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,+207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,++/* block 11 */+207,207,207,207,207,207,207,206,206,205,208,120,120,209,209,210,+120,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,+211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,+211,211,211,211,211,211,211,211,211,211,211,211,211,211,212,211,+213,211,211,213,211,211,213,211,120,120,120,120,120,120,120,120,+214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,+214,214,214,214,214,214,214,214,214,214,214,120,120,120,120,214,+214,214,214,213,213,120,120,120,120,120,120,120,120,120,120,120,++/* block 12 */+215,215,215,215,215,216,217,217,217,218,218,219,220,218,221,221,+222,222,222,222,222,222,222,222,222,222,222,220,223,120,218,220,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+225,224,224,224,224,224,224,224,224,224,224,226,226,226,226,226,+226,226,226,226,226,226,222,222,222,222,222,222,222,222,222,222,+227,227,227,227,227,227,227,227,227,227,218,218,218,218,224,224,+226,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,++/* block 13 */+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,228,224,222,222,222,222,222,222,222,216,221,222,+222,222,222,222,222,229,229,222,222,221,222,222,222,222,224,224,+230,230,230,230,230,230,230,230,230,230,224,224,224,221,221,224,++/* block 14 */+231,231,231,231,231,231,231,231,231,231,231,231,231,231,120,232,+233,234,233,233,233,233,233,233,233,233,233,233,233,233,233,233,+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,+234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,+234,234,234,234,234,234,234,234,234,234,234,120,120,233,233,233,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,++/* block 15 */+235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,+235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,+235,235,235,235,235,235,236,236,236,236,236,236,236,236,236,236,+236,235,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+237,237,237,237,237,237,237,237,237,237,238,238,238,238,238,238,+238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,+238,238,238,238,238,238,238,238,238,238,238,239,239,239,239,239,+239,239,239,239,240,240,241,242,242,242,240,120,120,239,243,243,++/* block 16 */+244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,+244,244,244,244,244,244,245,245,245,245,246,245,245,245,245,245,+245,245,245,245,246,245,245,245,246,245,245,245,245,245,120,120,+247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,120,+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,+248,248,248,248,248,248,248,248,248,249,249,249,120,120,250,120,+233,233,233,233,233,233,233,233,233,233,233,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 17 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,120,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,120,120,120,120,120,120,120,120,+120,120,120,222,222,222,222,222,222,222,222,222,222,222,222,222,+222,222,216,222,222,222,222,222,222,222,222,222,222,222,222,222,+222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,++/* block 18 */+251,251,251,252,253,253,253,253,253,253,253,253,253,253,253,253,+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,+253,253,253,253,253,253,253,253,253,253,251,252,251,253,252,252,+252,251,251,251,251,251,251,251,251,252,252,252,252,251,252,252,+253,254,255,113,113,251,251,251,253,253,253,253,253,253,253,253,+253,253,251,251,256,257,258,258,258,258,258,258,258,258,258,258,+259,260,253,253,253,253,253,253,253,253,253,253,253,253,253,253,++/* block 19 */+261,262,263,263,120,261,261,261,261,261,261,261,261,120,120,261,+261,120,120,261,261,261,261,261,261,261,261,261,261,261,261,261,+261,261,261,261,261,261,261,261,261,120,261,261,261,261,261,261,+261,120,261,120,120,120,261,261,261,261,120,120,262,261,264,263,+263,262,262,262,262,120,120,263,263,120,120,263,263,262,261,120,+120,120,120,120,120,120,120,264,120,120,120,120,261,261,120,261,+261,261,262,262,120,120,265,265,265,265,265,265,265,265,265,265,+261,261,266,266,267,267,267,267,267,267,268,266,261,269,262,120,++/* block 20 */+120,270,270,271,120,272,272,272,272,272,272,120,120,120,120,272,+272,120,120,272,272,272,272,272,272,272,272,272,272,272,272,272,+272,272,272,272,272,272,272,272,272,120,272,272,272,272,272,272,+272,120,272,272,120,272,272,120,272,272,120,120,270,120,271,271,+271,270,270,120,120,120,120,270,270,120,120,270,270,270,120,120,+120,270,120,120,120,120,120,120,120,272,272,272,272,120,272,120,+120,120,120,120,120,120,273,273,273,273,273,273,273,273,273,273,+270,270,272,272,272,270,274,120,120,120,120,120,120,120,120,120,++/* block 21 */+120,275,275,276,120,277,277,277,277,277,277,277,277,277,120,277,+277,277,120,277,277,277,277,277,277,277,277,277,277,277,277,277,+277,277,277,277,277,277,277,277,277,120,277,277,277,277,277,277,+277,120,277,277,120,277,277,277,277,277,120,120,275,277,276,276,+276,275,275,275,275,275,120,275,275,276,120,276,276,275,120,120,+277,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+277,277,275,275,120,120,278,278,278,278,278,278,278,278,278,278,+279,280,120,120,120,120,120,120,120,277,275,275,275,275,275,275,++/* block 22 */+120,281,282,282,120,283,283,283,283,283,283,283,283,120,120,283,+283,120,120,283,283,283,283,283,283,283,283,283,283,283,283,283,+283,283,283,283,283,283,283,283,283,120,283,283,283,283,283,283,+283,120,283,283,120,283,283,283,283,283,120,120,281,283,284,281,+282,281,281,281,281,120,120,282,282,120,120,282,282,281,120,120,+120,120,120,120,120,281,281,284,120,120,120,120,283,283,120,283,+283,283,281,281,120,120,285,285,285,285,285,285,285,285,285,285,+286,283,287,287,287,287,287,287,120,120,120,120,120,120,120,120,++/* block 23 */+120,120,288,289,120,289,289,289,289,289,289,120,120,120,289,289,+289,120,289,289,289,289,120,120,120,289,289,120,289,120,289,289,+120,120,120,289,289,120,120,120,289,289,289,120,120,120,289,289,+289,289,289,289,289,289,289,289,289,289,120,120,120,120,290,291,+288,291,291,120,120,120,291,291,291,120,291,291,291,288,120,120,+289,120,120,120,120,120,120,290,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,292,292,292,292,292,292,292,292,292,292,+293,293,293,294,295,295,295,295,295,296,295,120,120,120,120,120,++/* block 24 */+297,298,298,298,297,299,299,299,299,299,299,299,299,120,299,299,+299,120,299,299,299,299,299,299,299,299,299,299,299,299,299,299,+299,299,299,299,299,299,299,299,299,120,299,299,299,299,299,299,+299,299,299,299,299,299,299,299,299,299,120,120,120,299,297,297,+297,298,298,298,298,120,297,297,297,120,297,297,297,297,120,120,+120,120,120,120,120,297,297,120,299,299,299,120,120,120,120,120,+299,299,297,297,120,120,300,300,300,300,300,300,300,300,300,300,+120,120,120,120,120,120,120,301,302,302,302,302,302,302,302,303,++/* block 25 */+304,305,306,306,307,304,304,304,304,304,304,304,304,120,304,304,+304,120,304,304,304,304,304,304,304,304,304,304,304,304,304,304,+304,304,304,304,304,304,304,304,304,120,304,304,304,304,304,304,+304,304,304,304,120,304,304,304,304,304,120,120,305,304,306,305,+306,306,308,306,306,120,305,306,306,120,306,306,305,305,120,120,+120,120,120,120,120,308,308,120,120,120,120,120,120,120,304,120,+304,304,305,305,120,120,309,309,309,309,309,309,309,309,309,309,+120,304,304,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 26 */+310,310,311,311,312,312,312,312,312,312,312,312,312,120,312,312,+312,120,312,312,312,312,312,312,312,312,312,312,312,312,312,312,+312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,+312,312,312,312,312,312,312,312,312,312,312,310,310,312,313,311,+311,310,310,310,310,120,311,311,311,120,311,311,311,310,314,315,+120,120,120,120,312,312,312,313,316,316,316,316,316,316,316,312,+312,312,310,310,120,120,317,317,317,317,317,317,317,317,317,317,+316,316,316,316,316,316,316,316,316,315,312,312,312,312,312,312,++/* block 27 */+120,318,319,319,120,320,320,320,320,320,320,320,320,320,320,320,+320,320,320,320,320,320,320,120,120,120,320,320,320,320,320,320,+320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,+320,320,120,320,320,320,320,320,320,320,320,320,120,320,120,120,+320,320,320,320,320,320,320,120,120,120,318,120,120,120,120,321,+319,319,318,318,318,120,318,120,319,319,319,319,319,319,319,321,+120,120,120,120,120,120,322,322,322,322,322,322,322,322,322,322,+120,120,319,319,323,120,120,120,120,120,120,120,120,120,120,120,++/* block 28 */+120,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,+324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,+324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,+324,325,324,326,325,325,325,325,325,325,325,120,120,120,120, 6,+324,324,324,324,324,324,327,325,325,325,325,325,325,325,325,328,+329,329,329,329,329,329,329,329,329,329,328,328,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 29 */+120,330,330,120,330,120,330,330,330,330,330,120,330,330,330,330,+330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,+330,330,330,330,120,330,120,330,330,330,330,330,330,330,330,330,+330,331,330,332,331,331,331,331,331,331,331,331,331,330,120,120,+330,330,330,330,330,120,333,120,331,331,331,331,331,331,120,120,+334,334,334,334,334,334,334,334,334,334,120,120,330,330,330,330,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 30 */+335,336,336,336,337,337,337,337,337,337,337,337,337,337,337,337,+337,337,337,336,337,336,336,336,338,338,336,336,336,336,336,336,+339,339,339,339,339,339,339,339,339,339,340,340,340,340,340,340,+340,340,340,340,336,338,336,338,336,338,341,342,341,342,343,343,+335,335,335,335,335,335,335,335,120,335,335,335,335,335,335,335,+335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,+335,335,335,335,335,335,335,335,335,335,335,335,335,120,120,120,+120,338,338,338,338,338,338,338,338,338,338,338,338,338,338,343,++/* block 31 */+338,338,338,338,338,337,338,338,335,335,335,335,335,338,338,338,+338,338,338,338,338,338,338,338,120,338,338,338,338,338,338,338,+338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,+338,338,338,338,338,338,338,338,338,338,338,338,338,120,336,336,+336,336,336,336,336,336,338,336,336,336,336,336,336,120,336,336,+337,337,337,337,337, 20, 20, 20, 20,337,337,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 32 */+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,+344,344,344,344,344,344,344,344,344,344,344,345,345,346,346,346,+346,347,346,346,346,346,346,346,345,346,346,347,347,346,346,344,+348,348,348,348,348,348,348,348,348,348,349,349,349,349,349,349,+344,344,344,344,344,344,347,347,346,346,344,344,344,344,346,346,+346,344,345,345,345,344,344,345,345,345,345,345,345,345,344,344,+344,346,346,346,346,344,344,344,344,344,344,344,344,344,344,344,++/* block 33 */+344,344,346,345,347,346,346,345,345,345,345,345,345,346,344,345,+350,350,350,350,350,350,350,350,350,350,345,345,345,346,351,351,+352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,+352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,+352,352,352,352,352,352,120,352,120,120,120,120,120,352,120,120,+353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,+353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,+353,353,353,353,353,353,353,353,353,353,353,354,355,353,353,353,++/* block 34 */+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,+357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,+357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,++/* block 35 */+357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,+357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,+357,357,357,357,357,357,357,357,358,358,358,358,358,358,358,358,+358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,+358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,+358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,+358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,+358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,++/* block 36 */+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,120,359,359,359,359,120,120,+359,359,359,359,359,359,359,120,359,120,359,359,359,359,120,120,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,++/* block 37 */+359,359,359,359,359,359,359,359,359,120,359,359,359,359,120,120,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,120,359,359,359,359,120,120,359,359,359,359,359,359,359,120,+359,120,359,359,359,359,120,120,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,++/* block 38 */+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,120,359,359,359,359,120,120,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,359,359,359,359,120,120,360,360,360,+361,361,361,361,361,361,361,361,361,362,362,362,362,362,362,362,+362,362,362,362,362,362,362,362,362,362,362,362,362,120,120,120,++/* block 39 */+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+363,363,363,363,363,363,363,363,363,363,120,120,120,120,120,120,+364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,+364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,+364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,+364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,+364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,+365,365,365,365,365,365,120,120,366,366,366,366,366,366,120,120,++/* block 40 */+367,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,++/* block 41 */+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,++/* block 42 */+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,369,370,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,++/* block 43 */+371,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,+372,372,372,372,372,372,372,372,372,372,372,373,374,120,120,120,+375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,+375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,+375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,+375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,+375,375,375,375,375,375,375,375,375,375,375, 5, 5, 5,376,376,+376,375,375,375,375,375,375,375,375,120,120,120,120,120,120,120,++/* block 44 */+377,377,377,377,377,377,377,377,377,377,377,377,377,120,377,377,+377,377,378,378,378,120,120,120,120,120,120,120,120,120,120,120,+379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,+379,379,380,380,380,381,381,120,120,120,120,120,120,120,120,120,+382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,+382,382,383,383,120,120,120,120,120,120,120,120,120,120,120,120,+384,384,384,384,384,384,384,384,384,384,384,384,384,120,384,384,+384,120,385,385,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 45 */+386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,+386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,+386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,+386,386,386,386,387,387,388,387,387,387,387,387,387,387,388,388,+388,388,388,388,388,388,387,388,388,387,387,387,387,387,387,387,+387,387,387,387,389,389,389,390,389,389,389,391,386,387,120,120,+392,392,392,392,392,392,392,392,392,392,120,120,120,120,120,120,+393,393,393,393,393,393,393,393,393,393,120,120,120,120,120,120,++/* block 46 */+394,394,395,395,394,395,396,394,394,394,394,397,397,397,398,120,+399,399,399,399,399,399,399,399,399,399,120,120,120,120,120,120,+400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,+400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,+400,400,400,401,400,400,400,400,400,400,400,400,400,400,400,400,+400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,+400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,+400,400,400,400,400,400,400,400,400,120,120,120,120,120,120,120,++/* block 47 */+400,400,400,400,400,397,397,400,400,400,400,400,400,400,400,400,+400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,+400,400,400,400,400,400,400,400,400,397,400,120,120,120,120,120,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,+368,368,368,368,368,368,120,120,120,120,120,120,120,120,120,120,++/* block 48 */+402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,+402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,120,+403,403,403,404,404,404,404,403,403,404,404,404,120,120,120,120,+404,404,403,404,404,404,404,404,404,403,403,403,120,120,120,120,+405,120,120,120,406,406,407,407,407,407,407,407,407,407,407,407,+408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,+408,408,408,408,408,408,408,408,408,408,408,408,408,408,120,120,+408,408,408,408,408,120,120,120,120,120,120,120,120,120,120,120,++/* block 49 */+409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,+409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,+409,409,409,409,409,409,409,409,409,409,409,409,120,120,120,120,+409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,+409,409,409,409,409,409,409,409,409,409,120,120,120,120,120,120,+410,410,410,410,410,410,410,410,410,410,411,120,120,120,412,412,+413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,+413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,++/* block 50 */+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,+414,414,414,414,414,414,414,415,415,416,416,415,120,120,417,417,+418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,+418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,+418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,+418,418,418,418,418,419,420,419,420,420,420,420,420,420,420,120,+420,421,420,421,421,420,420,420,420,420,420,420,420,419,419,419,+419,419,419,420,420,420,420,420,420,420,420,420,420,120,120,420,++/* block 51 */+422,422,422,422,422,422,422,422,422,422,120,120,120,120,120,120,+422,422,422,422,422,422,422,422,422,422,120,120,120,120,120,120,+423,423,423,423,423,423,423,424,423,423,423,423,423,423,120,120,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,425,113,+113,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 52 */+426,426,426,426,427,428,428,428,428,428,428,428,428,428,428,428,+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,+428,428,428,428,426,429,426,426,426,426,426,427,426,427,427,427,+427,427,426,427,427,428,428,428,428,428,428,428,120,120,120,120,+430,430,430,430,430,430,430,430,430,430,431,431,431,431,431,431,+431,432,432,432,432,432,432,432,432,432,432,426,426,426,426,426,+426,426,426,426,432,432,432,432,432,432,432,432,432,120,120,120,++/* block 53 */+433,433,434,435,435,435,435,435,435,435,435,435,435,435,435,435,+435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,+435,434,433,433,433,433,434,434,433,433,434,433,433,433,435,435,+436,436,436,436,436,436,436,436,436,436,435,435,435,435,435,435,+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,+437,437,437,437,437,437,438,439,438,438,439,439,439,438,439,438,+438,438,439,439,120,120,120,120,120,120,120,120,440,440,440,440,++/* block 54 */+441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,+441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,+441,441,441,441,442,442,442,442,442,442,442,442,443,443,443,443,+443,443,443,443,442,442,443,443,120,120,120,444,444,444,444,444,+445,445,445,445,445,445,445,445,445,445,120,120,120,441,441,441,+446,446,446,446,446,446,446,446,446,446,447,447,447,447,447,447,+447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,+447,447,447,447,447,447,447,447,448,448,448,448,448,448,449,449,++/* block 55 */+450,451,452,453,454,455,456,457,458,120,120,120,120,120,120,120,+459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,+459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,+459,459,459,459,459,459,459,459,459,459,459,120,120,459,459,459,+460,460,460,460,460,460,460,460,120,120,120,120,120,120,120,120,+461,462,461,463,462,464,464,465,464,465,466,462,465,465,462,462,+465,467,462,462,462,462,462,462,462,468,469,470,470,464,470,470,+470,470,471,472,473,469,469,474,475,475,476,120,120,120,120,120,++/* block 56 */+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,+ 35, 35, 35, 35, 35, 35,128,128,128,128,128,477,110,110,110,110,+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,+110,110,110,110,110,110,110,110,110,110,110,110,110,121,121,121,+121,121,110,110,110,110,121,121,121,121,121, 35, 35, 35, 35, 35,+ 35, 35, 35, 35, 35, 35, 35, 35,478,479, 35, 35, 35,480, 35, 35,++/* block 57 */+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,481, 35,+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,110,110,110,110,110,+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,121,+114,114,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,482,113,120,113,113,113,113,113,++/* block 58 */+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+483,484, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,++/* block 59 */+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 35, 35, 35, 35, 35,485, 35, 35,486, 35,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,++/* block 60 */+487,487,487,487,487,487,487,487,488,488,488,488,488,488,488,488,+487,487,487,487,487,487,120,120,488,488,488,488,488,488,120,120,+487,487,487,487,487,487,487,487,488,488,488,488,488,488,488,488,+487,487,487,487,487,487,487,487,488,488,488,488,488,488,488,488,+487,487,487,487,487,487,120,120,488,488,488,488,488,488,120,120,+128,487,128,487,128,487,128,487,120,488,120,488,120,488,120,488,+487,487,487,487,487,487,487,487,488,488,488,488,488,488,488,488,+489,489,490,490,490,490,491,491,492,492,493,493,494,494,120,120,++/* block 61 */+487,487,487,487,487,487,487,487,495,495,495,495,495,495,495,495,+487,487,487,487,487,487,487,487,495,495,495,495,495,495,495,495,+487,487,487,487,487,487,487,487,495,495,495,495,495,495,495,495,+487,487,128,496,128,120,128,128,488,488,497,497,498,119,499,119,+119,119,128,496,128,120,128,128,500,500,500,500,498,119,119,119,+487,487,128,128,120,120,128,128,488,488,501,501,120,119,119,119,+487,487,128,128,128,169,128,128,488,488,502,502,174,119,119,119,+120,120,128,496,128,120,128,128,503,503,504,504,498,119,119,120,++/* block 62 */+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24,505,506, 24, 24,+ 10, 10, 10, 10, 10, 10, 5, 5, 23, 27, 7, 23, 23, 27, 7, 23,+ 5, 5, 5, 5, 5, 5, 5, 5,507,508, 24, 24, 24, 24, 24,509,+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, 27, 5,510, 5, 5, 16,+ 16, 5, 5, 5, 9, 7, 8, 5, 5,510, 5, 5, 5, 5, 5, 5,+ 5, 5, 9, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4,+ 24, 24, 24, 24, 24,511, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 25,110,120,120, 25, 25, 25, 25, 25, 25, 9, 9, 9, 7, 8,110,++/* block 63 */+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 9, 9, 9, 7, 8,120,+110,110,110,110,110,110,110,110,110,110,110,110,110,120,120,120,+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+113,113,113,113,113,113,113,113,113,113,113,113,113,425,425,425,+425,113,425,425,425,113,113,113,113,113,113,113,113,113,113,113,+512,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 64 */+ 20, 20,513, 20, 20, 20, 20,513, 20, 20,514,513,513,513,514,514,+513,513,513,514, 20,513, 20, 20, 9,513,513,513,513,513, 20, 20,+ 20, 20, 21, 20,513, 20,515, 20,513, 20,516,517,513,513, 20,514,+513,513,518,513,514,519,519,519,519,520, 20, 20,514,514,513,513,+ 9, 9, 9, 9, 9,513,514,514,514,514, 20, 9, 20, 20,521, 20,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,++/* block 65 */+524,524,524, 32, 33,524,524,524,524, 25, 20, 20,120,120,120,120,+ 9, 9, 9, 9,525, 21, 21, 21, 21, 21, 9, 9, 20, 20, 20, 20,+ 9, 20, 20, 9, 20, 20, 9, 20, 20, 21, 21, 20, 20, 20, 9, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 9,+ 20, 20, 9, 20, 9, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,++/* block 66 */+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,++/* block 67 */+ 20, 20, 20, 20, 20, 20, 20, 20, 7, 8, 7, 8, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 20, 20, 20, 20,+ 9, 9, 20, 20, 20, 20, 20, 20, 21, 7, 8, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 20, 20, 20,++/* block 68 */+ 20, 20, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 9, 9, 9,+ 9, 9, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 20, 20, 20, 20, 21, 21, 21, 20, 20, 20, 20, 20,++/* block 69 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,++/* block 70 */+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20,526,526,526,526,526,526,526,526,526,526,+526,526,527,526,526,526,526,526,526,526,526,526,526,526,526,526,+528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,+528,528,528,528,528,528,528,528,528,528, 25, 25, 25, 25, 25, 25,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,++/* block 71 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,++/* block 72 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 21, 9, 20, 20, 20, 20, 20, 20, 20, 20,+ 21, 9, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 9, 9, 9,525,525,525,525, 9,++/* block 73 */+ 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,525,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,++/* block 74 */+ 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,++/* block 75 */+ 21, 21, 21, 21, 21, 21, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 20, 21, 20, 21, 20, 20, 20, 20, 20, 20, 21, 20, 20,+ 20, 21, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 21, 20, 20, 21, 20, 20, 20, 20, 21, 20, 21, 20,+ 20, 20, 20, 21, 21, 21, 20, 21, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 21, 21, 21, 21, 21, 7, 8, 7, 8, 7, 8, 7, 8,+ 7, 8, 7, 8, 7, 8, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,++/* block 76 */+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+ 25, 25, 25, 25, 20, 21, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,+ 9, 9, 9, 9, 9, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,++/* block 77 */+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,++/* block 78 */+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9,525,525, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,++/* block 79 */+ 9, 9, 9, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7,+ 8, 7, 8, 7, 8, 7, 8, 7, 8, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 7, 8, 7, 8, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 8, 9, 9,++/* block 80 */+ 20, 20, 20, 20, 20, 21, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+ 9, 9, 9, 9, 9, 20, 20, 9, 9, 9, 9, 9, 9, 20, 20, 20,+ 21, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20,120,120, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,++/* block 81 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20,120, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,++/* block 82 */+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,120,+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,120,+ 32, 33,532,533,534,535,536, 32, 33, 32, 33, 32, 33,537,538,539,+540, 35, 32, 33, 35, 32, 33, 35, 35, 35, 35, 35,110,110,541,541,++/* block 83 */+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,+165,166,165,166,542,543,543,543,543,543,543,165,166,165,166,544,+544,544,165,166,120,120,120,120,120,545,545,545,545,546,545,545,++/* block 84 */+547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,+547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,+547,547,547,547,547,547,120,547,120,120,120,120,120,547,120,120,+548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,+548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,+548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,+548,548,548,548,548,548,548,548,120,120,120,120,120,120,120,549,+550,120,120,120,120,120,120,120,120,120,120,120,120,120,120,551,++/* block 85 */+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,359,120,120,120,120,120,120,120,120,120,+359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,120,+359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,120,+359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,120,+359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,120,+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,++/* block 86 */+ 5, 5, 23, 27, 23, 27, 5, 5, 5, 23, 27, 5, 23, 27, 5, 5,+ 5, 5, 5, 5, 5, 5, 5, 10, 5, 5, 10, 5, 23, 27, 5, 5,+ 23, 27, 7, 8, 7, 8, 7, 8, 7, 8, 5, 5, 5, 5, 5,111,+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 5, 5, 5, 5,+ 10, 5, 7,553, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,+ 20, 20, 5,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 87 */+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,120,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 88 */+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,++/* block 89 */+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,+554,554,554,554,554,554,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,++/* block 90 */+ 4,555,555,556, 20,557,558,559,560,561,560,561,560,561,560,561,+560,561, 20,562,560,561,560,561,560,561,560,561,563,564,565,565,+ 20,559,559,559,559,559,559,559,559,559,566,566,566,566,567,567,+568,569,569,569,569,569, 20,562,559,559,559,557,570,571,572,572,+120,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,++/* block 91 */+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,120,120,574,574,575,575,576,576,573,+577,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,+578,578,578,578,578,578,578,578,578,578,578,555,569,579,579,578,++/* block 92 */+120,120,120,120,120,580,580,580,580,580,580,580,580,580,580,580,+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,+120,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,++/* block 93 */+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,120,+572,572,582,582,582,582,572,572,572,572,572,572,572,572,572,572,+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,+572,572,572,572,120,120,120,120,120,120,120,120,120,120,120,120,+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,++/* block 94 */+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,120,+582,582,582,582,582,582,582,582,582,582,572,572,572,572,572,572,+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,+572,572,572,572,572,572,572,572, 25, 25, 25, 25, 25, 25, 25, 25,+ 20, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583, 20,++/* block 95 */+582,582,582,582,582,582,582,582,582,582,572,572,572,572,572,572,+572,572,572,572,572,572,572,584,572,584,572,572,572,572,572,572,+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,+572, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+572,572,572,572,572,572,572,572,572,572,572,572, 20, 20, 20, 20,+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,572,++/* block 96 */+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,+585,585,585,585,585,585,585,585,572,572,572,572,572,572,572,572,+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,+572, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,572,572,572,572,572,++/* block 97 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572, 20,++/* block 98 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,++/* block 99 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,++/* block 100 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,120,120,120,++/* block 101 */+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,588,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,++/* block 102 */+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,++/* block 103 */+587,587,587,587,587,587,587,587,587,587,587,587,587,120,120,120,+589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,+589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,+589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,+589,589,589,589,589,589,589,120,120,120,120,120,120,120,120,120,+590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,+590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,+590,590,590,590,590,590,590,590,591,591,591,591,591,591,592,592,++/* block 104 */+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,++/* block 105 */+593,593,593,593,593,593,593,593,593,593,593,593,594,595,595,595,+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,+596,596,596,596,596,596,596,596,596,596,593,593,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+192,193,192,193,192,193,192,193,192,193,597,598,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,192,193,599,198,+200,200,200,600,552,552,552,552,552,552,552,552,552,552,600,478,++/* block 106 */+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,+192,193,192,193,192,193,192,193,192,193,192,193,478,478,552,552,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,602,602,602,602,602,602,602,602,602,602,+603,603,604,604,604,604,604,604,120,120,120,120,120,120,120,120,++/* block 107 */+605,605,605,605,605,605,605,605, 15, 15, 15, 15, 15, 15, 15, 15,+ 15, 15, 15, 15, 15, 15, 15,111,111,111,111,111,111,111,111,111,+ 15, 15, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 35, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+110, 35, 35, 35, 35, 35, 35, 35, 35, 32, 33, 32, 33,606, 32, 33,++/* block 108 */+ 32, 33, 32, 33, 32, 33, 32, 33,111, 15, 15, 32, 33,607, 35, 22,+ 32, 33, 32, 33,608, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,609,610,611,612,609, 35,+613,614,615,616, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,+120,120, 32, 33,617,618,619, 32, 33, 32, 33,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120, 32, 33, 22,110,110, 35, 22, 22, 22, 22, 22,++/* block 109 */+620,620,621,620,620,620,621,620,620,620,620,621,620,620,620,620,+620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,+620,620,620,622,622,621,621,622,623,623,623,623,621,120,120,120,+624,624,624,625,625,625,626,626,627,626,120,120,120,120,120,120,+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,+628,628,628,628,629,629,629,629,120,120,120,120,120,120,120,120,++/* block 110 */+630,630,631,631,631,631,631,631,631,631,631,631,631,631,631,631,+631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,+631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,+631,631,631,631,630,630,630,630,630,630,630,630,630,630,630,630,+630,630,630,630,632,632,120,120,120,120,120,120,120,120,633,633,+634,634,634,634,634,634,634,634,634,634,120,120,120,120,120,120,+251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,+251,635,253,636,253,253,253,253,259,259,259,253,259,253,253,251,++/* block 111 */+637,637,637,637,637,637,637,637,637,637,638,638,638,638,638,638,+638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,+638,638,638,638,638,638,639,639,639,639,639,639,639,639,640,641,+642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,+642,642,642,642,642,642,642,643,643,643,643,643,643,643,643,643,+643,643,644,644,120,120,120,120,120,120,120,120,120,120,120,645,+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,+356,356,356,356,356,356,356,356,356,356,356,356,356,120,120,120,++/* block 112 */+646,646,646,647,648,648,648,648,648,648,648,648,648,648,648,648,+648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,+648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,+648,648,648,646,647,647,646,646,646,646,647,647,646,646,647,647,+647,649,649,649,649,649,649,649,649,649,649,649,649,649,120,650,+651,651,651,651,651,651,651,651,651,651,120,120,120,120,649,649,+344,344,344,344,344,346,652,344,344,344,344,344,344,344,344,344,+350,350,350,350,350,350,350,350,350,350,344,344,344,344,344,120,++/* block 113 */+653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,+653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,+653,653,653,653,653,653,653,653,653,654,654,654,654,654,654,655,+655,654,654,655,655,654,654,120,120,120,120,120,120,120,120,120,+653,653,653,654,653,653,653,653,653,653,653,653,654,655,120,120,+656,656,656,656,656,656,656,656,656,656,120,120,657,657,657,657,+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,+652,344,344,344,344,344,344,351,351,351,344,345,346,345,344,344,++/* block 114 */+658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,+658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,+658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,+659,658,659,659,659,658,658,659,659,658,658,658,658,658,659,659,+658,659,658,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,658,658,660,661,661,+662,662,662,662,662,662,662,662,662,662,662,663,664,664,663,663,+665,665,662,666,666,663,664,120,120,120,120,120,120,120,120,120,++/* block 115 */+120,359,359,359,359,359,359,120,120,359,359,359,359,359,359,120,+120,359,359,359,359,359,359,120,120,120,120,120,120,120,120,120,+359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,120,+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,+ 35, 35, 35,667, 35, 35, 35, 35, 35, 35, 35, 15,110,110,110,110,+ 35, 35, 35, 35, 35,128, 35, 35, 35,110, 15, 15,120,120,120,120,+668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,++/* block 116 */+668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,+668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,+668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,+668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,+662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,+662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,+662,662,662,663,663,664,663,663,664,663,663,665,663,664,120,120,+669,669,669,669,669,669,669,669,669,669,120,120,120,120,120,120,++/* block 117 */+670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,++/* block 118 */+671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671,++/* block 119 */+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,++/* block 120 */+671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671,++/* block 121 */+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,++/* block 122 */+671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671,++/* block 123 */+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,++/* block 124 */+671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671,+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,+671,671,671,671,120,120,120,120,120,120,120,120,120,120,120,120,+357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,+357,357,357,357,357,357,357,120,120,120,120,358,358,358,358,358,+358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,+358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,+358,358,358,358,358,358,358,358,358,358,358,358,120,120,120,120,++/* block 125 */+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,++/* block 126 */+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,++/* block 127 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,120,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,++/* block 128 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 129 */+ 35, 35, 35, 35, 35, 35, 35,120,120,120,120,120,120,120,120,120,+120,120,120,206,206,206,206,206,120,120,120,120,120,214,211,214,+214,214,214,214,214,214,214,214,214,674,214,214,214,214,214,214,+214,214,214,214,214,214,214,120,214,214,214,214,214,120,214,120,+214,214,120,214,214,120,214,214,214,214,214,214,214,214,214,214,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,++/* block 130 */+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,675,675,675,675,675,675,675,675,675,675,675,675,675,675,+675,675,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,++/* block 131 */+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,++/* block 132 */+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224, 8, 7,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,++/* block 133 */+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+120,120,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+224,224,676,224,224,224,224,224,224,224,224,224,219,677,120,120,++/* block 134 */+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+ 5, 5, 5, 5, 5, 5, 5, 7, 8, 5,120,120,120,120,120,120,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,552,552,+ 5, 10, 10, 16, 16, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7,+ 8, 7, 8, 7, 8,556,556, 7, 8, 5, 5, 5, 5, 16, 16, 16,+ 5, 5, 5,120, 5, 5, 5, 5, 10, 7, 8, 7, 8, 7, 8, 5,+ 5, 5, 9, 10, 9, 9, 9,120, 5, 6, 5, 5,120,120,120,120,+224,224,224,224,224,120,224,224,224,224,224,224,224,224,224,224,++/* block 135 */+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,120,120, 24,++/* block 136 */+120, 5, 5, 5, 6, 5, 5, 5, 7, 8, 5, 9, 5, 10, 5, 5,+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 5, 5, 9, 9, 9, 5,+ 5, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 5, 8, 15, 16,+ 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 7, 9, 8, 9, 7,+ 8,555,560,561,555,555,578,578,578,578,578,578,578,578,578,578,+569,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,++/* block 137 */+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,+578,578,578,578,578,578,578,578,578,578,578,578,578,578,678,678,+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,120,+120,120,581,581,581,581,581,581,120,120,581,581,581,581,581,581,+120,120,581,581,581,581,581,581,120,120,581,581,581,120,120,120,+ 6, 6, 9, 15, 20, 6, 6,120, 20, 9, 9, 9, 9, 20, 20,120,+511,511,511,511,511,511,511,511,511, 24, 24, 24, 20, 20,120,120,++/* block 138 */+679,679,679,679,679,679,679,679,679,679,679,679,120,679,679,679,+679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,+679,679,679,679,679,679,679,120,679,679,679,679,679,679,679,679,+679,679,679,679,679,679,679,679,679,679,679,120,679,679,120,679,+679,679,679,679,679,679,679,679,679,679,679,679,679,679,120,120,+679,679,679,679,679,679,679,679,679,679,679,679,679,679,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 139 */+679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,+679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,+679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,+679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,+679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,+679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,+679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,+679,679,679,679,679,679,679,679,679,679,679,120,120,120,120,120,++/* block 140 */+680,680,680,120,120,120,120,681,681,681,681,681,681,681,681,681,+681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,+681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,+681,681,681,681,120,120,120,682,682,682,682,682,682,682,682,682,+683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,+683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,+683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,+683,683,683,683,683,684,684,684,684,685,685,685,685,685,685,685,++/* block 141 */+685,685,685,685,685,685,685,685,685,685,684,684,685,685,685,120,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,+685,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,113,120,120,++/* block 142 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 143 */+686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,+686,686,686,686,686,686,686,686,686,686,686,686,686,120,120,120,+687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,+687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,+687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,+687,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+688,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,+689,689,689,689,689,689,689,689,689,689,689,689,120,120,120,120,++/* block 144 */+690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,+690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,+691,691,691,691,120,120,120,120,120,120,120,120,120,690,690,690,+692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,+692,693,692,692,692,692,692,692,692,692,693,120,120,120,120,120,+694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,+694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,+694,694,694,694,694,694,695,695,695,695,695,120,120,120,120,120,++/* block 145 */+696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,+696,696,696,696,696,696,696,696,696,696,696,696,696,696,120,697,+698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,+698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,+698,698,698,698,120,120,120,120,698,698,698,698,698,698,698,698,+699,700,700,700,700,700,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 146 */+701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,+701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,+701,701,701,701,701,701,701,701,702,702,702,702,702,702,702,702,+702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,+702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,+703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,+703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,+703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,++/* block 147 */+704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,+704,704,704,704,704,704,704,704,704,704,704,704,704,704,120,120,+705,705,705,705,705,705,705,705,705,705,120,120,120,120,120,120,+706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,+706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,+706,706,706,706,120,120,120,120,707,707,707,707,707,707,707,707,+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,+707,707,707,707,707,707,707,707,707,707,707,707,120,120,120,120,++/* block 148 */+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,+708,708,708,708,708,708,708,708,120,120,120,120,120,120,120,120,+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,+709,709,709,709,120,120,120,120,120,120,120,120,120,120,120,710,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 149 */+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,++/* block 150 */+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,711,120,120,120,120,120,120,120,120,120,+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,+711,711,711,711,711,711,120,120,120,120,120,120,120,120,120,120,+711,711,711,711,711,711,711,711,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 151 */+712,712,712,712,712,712,120,120,712,120,712,712,712,712,712,712,+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,+712,712,712,712,712,712,120,712,712,120,120,120,712,120,120,712,+713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,+713,713,713,713,713,713,120,714,715,715,715,715,715,715,715,715,+716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,+716,716,716,716,716,716,716,717,717,718,718,718,718,718,718,718,++/* block 152 */+719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,+719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,120,+120,120,120,120,120,120,120,720,720,720,720,720,720,720,720,720,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,+721,721,721,120,721,721,120,120,120,120,120,722,722,722,722,722,++/* block 153 */+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,+723,723,723,723,723,723,724,724,724,724,724,724,120,120,120,725,+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,+726,726,726,726,726,726,726,726,726,726,120,120,120,120,120,727,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 154 */+728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,+728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,+729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,+729,729,729,729,729,729,729,729,120,120,120,120,730,730,729,729,+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,+120,120,730,730,730,730,730,730,730,730,730,730,730,730,730,730,+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,++/* block 155 */+731,732,732,732,120,732,732,120,120,120,120,120,732,732,732,732,+731,731,731,731,120,731,731,731,120,731,731,731,731,731,731,731,+731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,+731,731,731,731,731,731,120,120,732,732,732,120,120,120,120,732,+733,733,733,733,733,733,733,733,733,120,120,120,120,120,120,120,+734,734,734,734,734,734,734,734,734,120,120,120,120,120,120,120,+735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,+735,735,735,735,735,735,735,735,735,735,735,735,735,736,736,737,++/* block 156 */+738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,+738,738,738,738,738,738,738,738,738,738,738,738,738,739,739,739,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+740,740,740,740,740,740,740,740,741,740,740,740,740,740,740,740,+740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,+740,740,740,740,740,742,742,120,120,120,120,743,743,743,743,743,+744,744,744,744,744,744,744,120,120,120,120,120,120,120,120,120,++/* block 157 */+745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,+745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,+745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,+745,745,745,745,745,745,120,120,120,746,746,746,746,746,746,746,+747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,+747,747,747,747,747,747,120,120,748,748,748,748,748,748,748,748,+749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,+749,749,749,120,120,120,120,120,750,750,750,750,750,750,750,750,++/* block 158 */+751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,+751,751,120,120,120,120,120,120,120,752,752,752,752,120,120,120,+120,120,120,120,120,120,120,120,120,753,753,753,753,753,753,753,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 159 */+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,+754,754,754,754,754,754,754,754,754,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 160 */+755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,+755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,+755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,+755,755,755,120,120,120,120,120,120,120,120,120,120,120,120,120,+756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,+756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,+756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,+756,756,756,120,120,120,120,120,120,120,757,757,757,757,757,757,++/* block 161 */+758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,+758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,+758,758,758,758,759,759,759,759,120,120,120,120,120,120,120,120,+760,760,760,760,760,760,760,760,760,760,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 162 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,+761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,120,++/* block 163 */+762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,+762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,+762,762,762,762,762,762,762,762,762,762,120,763,763,764,120,120,+762,762,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 164 */+765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,+765,765,765,765,765,765,765,765,765,765,765,765,765,766,766,766,+766,766,766,766,766,766,766,765,120,120,120,120,120,120,120,120,+767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,+767,767,767,767,767,767,768,768,768,768,768,768,768,768,768,768,+768,769,769,769,769,770,770,770,770,770,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 165 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,+771,771,771,771,771,772,772,772,772,772,772,772,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,+773,773,773,773,773,773,773,120,120,120,120,120,120,120,120,120,++/* block 166 */+774,775,774,776,776,776,776,776,776,776,776,776,776,776,776,776,+776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,+776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,+776,776,776,776,776,776,776,776,775,775,775,775,775,775,775,775,+775,775,775,775,775,775,775,777,777,777,777,777,777,777,120,120,+120,120,778,778,778,778,778,778,778,778,778,778,778,778,778,778,+778,778,778,778,778,778,779,779,779,779,779,779,779,779,779,779,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,775,++/* block 167 */+780,780,781,782,782,782,782,782,782,782,782,782,782,782,782,782,+782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,+782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,+781,781,781,780,780,780,780,781,781,780,780,783,783,784,783,783,+783,783,120,120,120,120,120,120,120,120,120,120,120,784,120,120,+785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,+785,785,785,785,785,785,785,785,785,120,120,120,120,120,120,120,+786,786,786,786,786,786,786,786,786,786,120,120,120,120,120,120,++/* block 168 */+787,787,787,788,788,788,788,788,788,788,788,788,788,788,788,788,+788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,+788,788,788,788,788,788,788,787,787,787,787,787,789,787,787,787,+787,787,787,787,787,120,790,790,790,790,790,790,790,790,790,790,+791,791,791,791,788,789,789,788,120,120,120,120,120,120,120,120,+792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,+792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,+792,792,792,793,794,794,792,120,120,120,120,120,120,120,120,120,++/* block 169 */+795,795,796,797,797,797,797,797,797,797,797,797,797,797,797,797,+797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,+797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,+797,797,797,796,796,796,795,795,795,795,795,795,795,795,795,796,+796,797,798,798,797,799,799,799,799,795,795,795,795,799,796,795,+800,800,800,800,800,800,800,800,800,800,797,799,797,799,799,799,+120,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,+801,801,801,801,801,120,120,120,120,120,120,120,120,120,120,120,++/* block 170 */+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,+802,802,120,802,802,802,802,802,802,802,802,802,802,802,802,802,+802,802,802,802,802,802,802,802,802,802,802,802,803,803,803,804,+804,804,803,803,804,803,804,804,805,805,805,805,805,805,804,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 171 */+806,806,806,806,806,806,806,120,806,120,806,806,806,806,120,806,+806,806,806,806,806,806,806,806,806,806,806,806,806,806,120,806,+806,806,806,806,806,806,806,806,806,807,120,120,120,120,120,120,+808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,+808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,+808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,809,+810,810,810,809,809,809,809,809,809,809,809,120,120,120,120,120,+811,811,811,811,811,811,811,811,811,811,120,120,120,120,120,120,++/* block 172 */+812,813,814,815,120,816,816,816,816,816,816,816,816,120,120,816,+816,120,120,816,816,816,816,816,816,816,816,816,816,816,816,816,+816,816,816,816,816,816,816,816,816,120,816,816,816,816,816,816,+816,120,816,816,120,816,816,816,816,816,120,817,813,816,818,814,+812,814,814,814,814,120,120,814,814,120,120,814,814,814,120,120,+816,120,120,120,120,120,120,818,120,120,120,120,120,816,816,816,+816,816,814,814,120,120,812,812,812,812,812,812,812,120,120,120,+812,812,812,812,812,120,120,120,120,120,120,120,120,120,120,120,++/* block 173 */+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,+819,819,819,819,819,820,820,820,821,821,821,821,821,821,821,821,+820,820,821,821,821,820,821,819,819,819,819,822,822,822,822,822,+823,823,823,823,823,823,823,823,823,823,822,822,120,822,821,819,+819,819,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 174 */+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,+825,826,826,827,827,827,827,827,827,826,827,826,826,825,826,827,+827,826,827,827,824,824,828,824,120,120,120,120,120,120,120,120,+829,829,829,829,829,829,829,829,829,829,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 175 */+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,831,+832,832,833,833,833,833,120,120,832,832,832,832,833,833,832,833,+833,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,+834,834,834,834,834,834,834,834,830,830,830,830,833,833,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 176 */+835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,+835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,+835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,+836,836,836,837,837,837,837,837,837,837,837,836,836,837,836,837,+837,838,838,838,835,120,120,120,120,120,120,120,120,120,120,120,+839,839,839,839,839,839,839,839,839,839,120,120,120,120,120,120,+394,394,394,394,394,394,394,394,394,394,394,394,394,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 177 */+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,+840,840,840,840,840,840,840,840,840,840,840,841,842,841,842,842,+841,841,841,841,841,841,842,841,840,120,120,120,120,120,120,120,+843,843,843,843,843,843,843,843,843,843,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 178 */+844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,+844,844,844,844,844,844,844,844,844,844,844,120,120,845,845,845,+846,846,845,845,845,845,846,845,845,845,845,845,120,120,120,120,+847,847,847,847,847,847,847,847,847,847,848,848,849,849,849,850,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 179 */+851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,+851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,+851,851,851,851,851,851,851,851,851,851,851,851,852,852,852,853,+853,853,853,853,853,853,853,853,852,853,853,854,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 180 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,+855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,+856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,+856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,+857,857,857,857,857,857,857,857,857,857,858,858,858,858,858,858,+858,858,858,120,120,120,120,120,120,120,120,120,120,120,120,859,++/* block 181 */+860,860,860,860,860,860,860,120,120,860,120,120,860,860,860,860,+860,860,860,860,120,860,860,120,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+861,862,862,862,862,862,120,862,862,120,120,863,863,862,863,864,+862,864,862,863,865,865,865,120,120,120,120,120,120,120,120,120,+866,866,866,866,866,866,866,866,866,866,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 182 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+867,867,867,867,867,867,867,867,120,120,867,867,867,867,867,867,+867,867,867,867,867,867,867,867,867,867,867,867,867,867,867,867,+867,867,867,867,867,867,867,867,867,867,867,867,867,867,867,867,+867,868,868,868,869,869,869,869,120,120,869,869,868,868,868,868,+869,867,870,867,868,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 183 */+871,872,872,872,872,872,872,872,872,872,872,871,871,871,871,871,+871,871,871,871,871,871,871,871,871,871,871,871,871,871,871,871,+871,871,871,871,871,871,871,871,871,871,871,871,871,871,871,871,+871,871,871,872,872,872,872,872,872,873,874,872,872,872,872,875,+875,875,875,875,875,875,875,872,120,120,120,120,120,120,120,120,+876,877,877,877,877,877,877,878,878,877,877,877,876,876,876,876,+876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,+876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,++/* block 184 */+876,876,876,876,879,879,879,879,879,879,877,877,877,877,877,877,+877,877,877,877,877,877,877,878,877,877,880,880,880,876,880,880,+880,880,880,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,+881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,+881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,+881,881,881,881,881,881,881,881,881,120,120,120,120,120,120,120,++/* block 185 */+882,882,882,882,882,882,882,882,882,120,882,882,882,882,882,882,+882,882,882,882,882,882,882,882,882,882,882,882,882,882,882,882,+882,882,882,882,882,882,882,882,882,882,882,882,882,882,882,883,+884,884,884,884,884,884,884,120,884,884,884,884,884,884,883,884,+882,885,885,885,885,885,120,120,120,120,120,120,120,120,120,120,+886,886,886,886,886,886,886,886,886,886,887,887,887,887,887,887,+887,887,887,887,887,887,887,887,887,887,887,887,887,120,120,120,+888,888,889,889,889,889,889,889,889,889,889,889,889,889,889,889,++/* block 186 */+889,889,889,889,889,889,889,889,889,889,889,889,889,889,889,889,+120,120,890,890,890,890,890,890,890,890,890,890,890,890,890,890,+890,890,890,890,890,890,890,890,120,891,890,890,890,890,890,890,+890,891,890,890,891,890,890,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 187 */+892,892,892,892,892,892,892,120,892,892,120,892,892,892,892,892,+892,892,892,892,892,892,892,892,892,892,892,892,892,892,892,892,+892,892,892,892,892,892,892,892,892,892,892,892,892,892,892,892,+892,893,893,893,893,893,893,120,120,120,893,120,893,893,120,893,+893,893,893,893,893,893,894,893,120,120,120,120,120,120,120,120,+895,895,895,895,895,895,895,895,895,895,120,120,120,120,120,120,+896,896,896,896,896,896,120,896,896,120,896,896,896,896,896,896,+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,++/* block 188 */+896,896,896,896,896,896,896,896,896,896,897,897,897,897,897,120,+898,898,120,897,897,898,897,898,896,120,120,120,120,120,120,120,+899,899,899,899,899,899,899,899,899,899,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 189 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,+900,900,900,901,901,902,902,903,903,120,120,120,120,120,120,120,++/* block 190 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+590,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+904,904,904,904,904,904,904,904,904,904,904,904,904,904,904,904,+293,293,904,293,904,295,295,295,295,295,295,295,295,296,296,296,+296,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,+295,295,120,120,120,120,120,120,120,120,120,120,120,120,120,905,++/* block 191 */+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,++/* block 192 */+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 193 */+907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,+907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,+907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,+907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,+907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,+907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,+907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,120,+908,908,908,908,908,120,120,120,120,120,120,120,120,120,120,120,++/* block 194 */+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,+906,906,906,906,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 195 */+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,++/* block 196 */+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,120,+910,910,910,910,910,910,910,910,910,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 197 */+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,++/* block 198 */+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 199 */+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,++/* block 200 */+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,+601,601,601,601,601,601,601,601,601,120,120,120,120,120,120,120,+912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,+912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,120,+913,913,913,913,913,913,913,913,913,913,120,120,120,120,914,914,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 201 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,+915,915,915,915,915,915,915,915,915,915,915,915,915,915,120,120,+916,916,916,916,916,917,120,120,120,120,120,120,120,120,120,120,++/* block 202 */+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+919,919,919,919,919,919,919,920,920,920,920,920,921,921,921,921,+922,922,922,922,920,921,120,120,120,120,120,120,120,120,120,120,+923,923,923,923,923,923,923,923,923,923,120,924,924,924,924,924,+924,924,120,918,918,918,918,918,918,918,918,918,918,918,918,918,+918,918,918,918,918,918,918,918,120,120,120,120,120,918,918,918,++/* block 203 */+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 204 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+925,925,925,925,925,925,925,925,925,925,925,925,925,925,925,925,+925,925,925,925,925,925,925,925,925,925,925,925,925,925,925,925,+926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,+926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,++/* block 205 */+927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,+927,927,927,927,927,927,927,928,928,928,928,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 206 */+929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,+929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,+929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,+929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,+929,929,929,929,929,929,929,929,929,929,929,120,120,120,120,930,+929,931,931,931,931,931,931,931,931,931,931,931,931,931,931,931,+931,931,931,931,931,931,931,931,931,931,931,931,931,931,931,931,+931,931,931,931,931,931,931,931,931,931,931,931,931,931,931,931,++/* block 207 */+931,931,931,931,931,931,931,931,120,120,120,120,120,120,120,930,+930,930,930,932,932,932,932,932,932,932,932,932,932,932,932,932,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+933,934, 5,111,935,120,120,120,120,120,120,120,120,120,120,120,+936,936,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 208 */+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,++/* block 209 */+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,+937,937,937,937,937,937,937,937,120,120,120,120,120,120,120,120,++/* block 210 */+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,++/* block 211 */+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,+938,938,938,938,938,938,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 212 */+937,937,937,937,937,937,937,937,937,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 213 */+578,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,++/* block 214 */+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,++/* block 215 */+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+573,573,573,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,578,578,578,578,120,120,120,120,120,120,120,120,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,++/* block 216 */+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,++/* block 217 */+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,+939,939,939,939,939,939,939,939,939,939,939,939,120,120,120,120,++/* block 218 */+940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,+940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,+940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,+940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,+940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,+940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,+940,940,940,940,940,940,940,940,940,940,940,120,120,120,120,120,+940,940,940,940,940,940,940,940,940,940,940,940,940,120,120,120,++/* block 219 */+940,940,940,940,940,940,940,940,940,120,120,120,120,120,120,120,+940,940,940,940,940,940,940,940,940,940,120,120,941,942,942,943,+944,944,944,944,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 220 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,120,++/* block 221 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20,120,120, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20,945,946,113,113,113, 20, 20, 20,946,945,945,+945,945,945, 24, 24, 24, 24, 24, 24, 24, 24,113,113,113,113,113,++/* block 222 */+113,113,113, 20, 20,113,113,113,113,113,113,113, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,113,113,113,113, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 223 */+685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,+685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,+685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,+685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,+685,685,947,947,947,685,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 224 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+ 25, 25, 25, 25,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 225 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,+582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,+582,582, 25, 25, 25, 25, 25, 25, 25,120,120,120,120,120,120,120,++/* block 226 */+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,513,513,513,513,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,514,514,+514,514,514,514,514,120,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,++/* block 227 */+513,513,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,513,120,513,513,+120,120,513,120,120,513,513,120,120,513,513,513,513,120,513,513,+513,513,513,513,513,513,514,514,514,514,120,514,120,514,514,514,+514,514,514,514,120,514,514,514,514,514,514,514,514,514,514,514,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,++/* block 228 */+514,514,514,514,513,513,120,513,513,513,513,120,120,513,513,513,+513,513,513,513,513,120,513,513,513,513,513,513,513,120,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,513,513,120,513,513,513,513,120,+513,513,513,513,513,120,513,120,120,120,513,513,513,513,513,513,+513,120,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,++/* block 229 */+513,513,513,513,513,513,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,513,513,513,513,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,++/* block 230 */+514,514,514,514,514,514,514,514,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,+513,513,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,++/* block 231 */+513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514,514,120,120,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,+513, 9,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514, 9,514,514,514,514,+514,514,513,513,513,513,513,513,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,513, 9,514,514,514,514,++/* block 232 */+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514, 9,514,514,514,514,514,514,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,+513,513,513,513,513, 9,514,514,514,514,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, 9,+514,514,514,514,514,514,513,513,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, 9,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,++/* block 233 */+514,514,514,514,514,514,514,514,514, 9,514,514,514,514,514,514,+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,+513,513,513,513,513,513,513,513,513, 9,514,514,514,514,514,514,+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,+514,514,514, 9,514,514,514,514,514,514,513,514,120,120, 11, 11,+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,++/* block 234 */+948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,+948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,+948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,+948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,+948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,+948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,+948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,+948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,++/* block 235 */+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,948,948,948,948,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+949,949,949,949,949,949,949,949,949,949,949,949,949,948,948,948,+948,948,948,948,948,949,948,948,948,948,948,948,948,948,948,948,++/* block 236 */+948,948,948,948,949,948,948,950,950,950,950,950,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,949,949,949,949,949,+120,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 237 */+951,951,951,951,951,951,951,120,951,951,951,951,951,951,951,951,+951,951,951,951,951,951,951,951,951,120,120,951,951,951,951,951,+951,951,120,951,951,120,951,951,951,951,951,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 238 */+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,+952,952,952,952,952,952,952,952,952,952,952,952,952,120,120,120,+953,953,953,953,953,953,953,954,954,954,954,954,954,954,120,120,+955,955,955,955,955,955,955,955,955,955,120,120,120,120,952,956,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 239 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,+957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,+957,957,957,957,957,957,957,957,957,957,957,957,958,958,958,958,+959,959,959,959,959,959,959,959,959,959,120,120,120,120,120,960,++/* block 240 */+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,++/* block 241 */+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,+961,961,961,961,961,120,120,962,962,962,962,962,962,962,962,962,+963,963,963,963,963,963,963,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 242 */+964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,+964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,+964,964,965,965,965,965,965,965,965,965,965,965,965,965,965,965,+965,965,965,965,965,965,965,965,965,965,965,965,965,965,965,965,+965,965,965,965,966,966,966,966,966,966,966,967,120,120,120,120,+968,968,968,968,968,968,968,968,968,968,120,120,120,120,969,969,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 243 */+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,++/* block 244 */+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 25, 25, 25,+ 6, 25, 25, 25, 25,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 245 */+120, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 25,+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 246 */+224,224,224,224,120,224,224,224,224,224,224,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,+120,224,224,120,224,120,120,224,120,224,224,224,224,224,224,224,+224,224,224,120,224,224,224,224,120,224,120,224,120,120,120,120,+120,120,224,120,120,120,120,224,120,224,120,224,120,224,224,224,+120,224,224,120,224,120,120,224,120,224,120,224,120,224,120,224,+120,224,224,120,224,120,120,224,224,224,224,120,224,224,224,224,+224,224,224,120,224,224,224,224,120,224,224,224,224,120,224,120,++/* block 247 */+224,224,224,224,224,224,224,224,224,224,120,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,120,120,120,120,+120,224,224,224,120,224,224,224,224,224,120,224,224,224,224,224,+224,224,224,224,224,224,224,224,224,224,224,224,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+217,217,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 248 */+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,970,970,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,++/* block 249 */+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,970,970,970,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,+970, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+970, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+970, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,970,++/* block 250 */+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 21, 21, 21,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21,+ 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21,++/* block 251 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 20,+ 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,971,971,971,971,971,971,971,971,971,971,+971,971,971,971,971,971,971,971,971,971,971,971,971,971,971,971,++/* block 252 */+972, 21, 21,970,970,970,970,970,970,970,970,970,970,970,970,970,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,+ 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20,970,970,970,970,+ 20, 20, 20, 20, 20, 20, 20, 20, 20,970,970,970,970,970,970,970,+584,584,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+ 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,++/* block 253 */+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,++/* block 254 */+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,++/* block 255 */+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,973,973,973,973,973,++/* block 256 */+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20,+ 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,++/* block 257 */+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,++/* block 258 */+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,970,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,970,++/* block 259 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20,970,970,970,970,970,970,970,970,970,970,970,970,++/* block 260 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 21, 21, 21, 21,970,970,970,970,970,970,970,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,++/* block 261 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,970,970,970,970,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20,970,970,970,970,970,970,970,970,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,970,970,970,970,970,970,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,++/* block 262 */+ 20, 20, 20, 20, 20, 20, 20, 20,970,970,970,970,970,970,970,970,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,970,970,+ 21, 21,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,++/* block 263 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21,970, 21, 21, 21, 21, 21, 21,++/* block 264 */+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,++/* block 265 */+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,970,970,970,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,+ 21, 21, 21, 21, 21,970,970,970, 21, 21, 21,970,970,970,970,970,++/* block 266 */+ 21, 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,+ 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,+ 21, 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,+ 21, 21, 21,970,970,970,970,970,970,970,970,970,970,970,970,970,+ 21, 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,++/* block 267 */+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20,120, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,120,120,120,120,120,120,++/* block 268 */+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,+970,970,970,970,970,970,970,970,970,970,970,970,970,970,120,120,++/* block 269 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 270 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,120,120,120,120,120,120,120,120,120,120,120,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,++/* block 271 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,120,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,++/* block 272 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,++/* block 273 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 274 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 275 */+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,+586,586,586,586,586,586,586,586,586,586,586,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,++/* block 276 */+511, 24,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,+974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,+974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,+974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,+974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,+974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,++/* block 277 */+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,++/* block 278 */+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,++/* block 279 */+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,++/* block 280 */+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,+673,673,673,673,673,673,673,673,673,673,673,673,673,673,120,120,++};++#if UCD_BLOCK_SIZE != 128+#error Please correct UCD_BLOCK_SIZE in pcre2_internal.h+#endif+#endif /* SUPPORT_UNICODE */++#endif /* PCRE2_PCRE2TEST */
+ src/c/pcre2/src/pcre2_ucp.h view
@@ -0,0 +1,299 @@+/*************************************************+* 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) 2016-2018 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.+-----------------------------------------------------------------------------+*/+++#ifndef PCRE2_UCP_H_IDEMPOTENT_GUARD+#define PCRE2_UCP_H_IDEMPOTENT_GUARD++/* This file contains definitions of the property values that are returned by+the UCD access macros. New values that are added for new releases of Unicode+should always be at the end of each enum, for backwards compatibility.++IMPORTANT: Note also that the specific numeric values of the enums have to be+the same as the values that are generated by the maint/MultiStage2.py script,+where the equivalent property descriptive names are listed in vectors.++ALSO: The specific values of the first two enums are assumed for the table+called catposstab in pcre2_compile.c. */++/* These are the general character categories. */++enum {+ ucp_C, /* Other */+ ucp_L, /* Letter */+ ucp_M, /* Mark */+ ucp_N, /* Number */+ ucp_P, /* Punctuation */+ ucp_S, /* Symbol */+ ucp_Z /* Separator */+};++/* These are the particular character categories. */++enum {+ ucp_Cc, /* Control */+ ucp_Cf, /* Format */+ ucp_Cn, /* Unassigned */+ ucp_Co, /* Private use */+ ucp_Cs, /* Surrogate */+ ucp_Ll, /* Lower case letter */+ ucp_Lm, /* Modifier letter */+ ucp_Lo, /* Other letter */+ ucp_Lt, /* Title case letter */+ ucp_Lu, /* Upper case letter */+ ucp_Mc, /* Spacing mark */+ ucp_Me, /* Enclosing mark */+ ucp_Mn, /* Non-spacing mark */+ ucp_Nd, /* Decimal number */+ ucp_Nl, /* Letter number */+ ucp_No, /* Other number */+ ucp_Pc, /* Connector punctuation */+ ucp_Pd, /* Dash punctuation */+ ucp_Pe, /* Close punctuation */+ ucp_Pf, /* Final punctuation */+ ucp_Pi, /* Initial punctuation */+ ucp_Po, /* Other punctuation */+ ucp_Ps, /* Open punctuation */+ ucp_Sc, /* Currency symbol */+ ucp_Sk, /* Modifier symbol */+ ucp_Sm, /* Mathematical symbol */+ ucp_So, /* Other symbol */+ ucp_Zl, /* Line separator */+ ucp_Zp, /* Paragraph separator */+ ucp_Zs /* Space separator */+};++/* These are grapheme break properties. The Extended Pictographic property+comes from the emoji-data.txt file. */++enum {+ ucp_gbCR, /* 0 */+ ucp_gbLF, /* 1 */+ ucp_gbControl, /* 2 */+ ucp_gbExtend, /* 3 */+ ucp_gbPrepend, /* 4 */+ ucp_gbSpacingMark, /* 5 */+ ucp_gbL, /* 6 Hangul syllable type L */+ ucp_gbV, /* 7 Hangul syllable type V */+ ucp_gbT, /* 8 Hangul syllable type T */+ ucp_gbLV, /* 9 Hangul syllable type LV */+ ucp_gbLVT, /* 10 Hangul syllable type LVT */+ ucp_gbRegionalIndicator, /* 11 */+ ucp_gbOther, /* 12 */+ ucp_gbZWJ, /* 13 */+ ucp_gbExtended_Pictographic /* 14 */+};++/* These are the script identifications. */++enum {+ ucp_Unknown,+ ucp_Arabic,+ ucp_Armenian,+ ucp_Bengali,+ ucp_Bopomofo,+ ucp_Braille,+ ucp_Buginese,+ ucp_Buhid,+ ucp_Canadian_Aboriginal,+ ucp_Cherokee,+ ucp_Common,+ ucp_Coptic,+ ucp_Cypriot,+ ucp_Cyrillic,+ ucp_Deseret,+ ucp_Devanagari,+ ucp_Ethiopic,+ ucp_Georgian,+ ucp_Glagolitic,+ ucp_Gothic,+ ucp_Greek,+ ucp_Gujarati,+ ucp_Gurmukhi,+ ucp_Han,+ ucp_Hangul,+ ucp_Hanunoo,+ ucp_Hebrew,+ ucp_Hiragana,+ ucp_Inherited,+ ucp_Kannada,+ ucp_Katakana,+ ucp_Kharoshthi,+ ucp_Khmer,+ ucp_Lao,+ ucp_Latin,+ ucp_Limbu,+ ucp_Linear_B,+ ucp_Malayalam,+ ucp_Mongolian,+ ucp_Myanmar,+ ucp_New_Tai_Lue,+ ucp_Ogham,+ ucp_Old_Italic,+ ucp_Old_Persian,+ ucp_Oriya,+ ucp_Osmanya,+ ucp_Runic,+ ucp_Shavian,+ ucp_Sinhala,+ ucp_Syloti_Nagri,+ ucp_Syriac,+ ucp_Tagalog,+ ucp_Tagbanwa,+ ucp_Tai_Le,+ ucp_Tamil,+ ucp_Telugu,+ ucp_Thaana,+ ucp_Thai,+ ucp_Tibetan,+ ucp_Tifinagh,+ ucp_Ugaritic,+ ucp_Yi,+ /* New for Unicode 5.0 */+ ucp_Balinese,+ ucp_Cuneiform,+ ucp_Nko,+ ucp_Phags_Pa,+ ucp_Phoenician,+ /* New for Unicode 5.1 */+ ucp_Carian,+ ucp_Cham,+ ucp_Kayah_Li,+ ucp_Lepcha,+ ucp_Lycian,+ ucp_Lydian,+ ucp_Ol_Chiki,+ ucp_Rejang,+ ucp_Saurashtra,+ ucp_Sundanese,+ ucp_Vai,+ /* New for Unicode 5.2 */+ ucp_Avestan,+ ucp_Bamum,+ ucp_Egyptian_Hieroglyphs,+ ucp_Imperial_Aramaic,+ ucp_Inscriptional_Pahlavi,+ ucp_Inscriptional_Parthian,+ ucp_Javanese,+ ucp_Kaithi,+ ucp_Lisu,+ ucp_Meetei_Mayek,+ ucp_Old_South_Arabian,+ ucp_Old_Turkic,+ ucp_Samaritan,+ ucp_Tai_Tham,+ ucp_Tai_Viet,+ /* New for Unicode 6.0.0 */+ ucp_Batak,+ ucp_Brahmi,+ ucp_Mandaic,+ /* New for Unicode 6.1.0 */+ ucp_Chakma,+ ucp_Meroitic_Cursive,+ ucp_Meroitic_Hieroglyphs,+ ucp_Miao,+ ucp_Sharada,+ ucp_Sora_Sompeng,+ ucp_Takri,+ /* New for Unicode 7.0.0 */+ ucp_Bassa_Vah,+ ucp_Caucasian_Albanian,+ ucp_Duployan,+ ucp_Elbasan,+ ucp_Grantha,+ ucp_Khojki,+ ucp_Khudawadi,+ ucp_Linear_A,+ ucp_Mahajani,+ ucp_Manichaean,+ ucp_Mende_Kikakui,+ ucp_Modi,+ ucp_Mro,+ ucp_Nabataean,+ ucp_Old_North_Arabian,+ ucp_Old_Permic,+ ucp_Pahawh_Hmong,+ ucp_Palmyrene,+ ucp_Psalter_Pahlavi,+ ucp_Pau_Cin_Hau,+ ucp_Siddham,+ ucp_Tirhuta,+ ucp_Warang_Citi,+ /* New for Unicode 8.0.0 */+ ucp_Ahom,+ ucp_Anatolian_Hieroglyphs,+ ucp_Hatran,+ ucp_Multani,+ ucp_Old_Hungarian,+ ucp_SignWriting,+ /* New for Unicode 10.0.0 (no update since 8.0.0) */+ ucp_Adlam,+ ucp_Bhaiksuki,+ ucp_Marchen,+ ucp_Newa,+ ucp_Osage,+ ucp_Tangut,+ ucp_Masaram_Gondi,+ ucp_Nushu,+ ucp_Soyombo,+ ucp_Zanabazar_Square,+ /* New for Unicode 11.0.0 */+ ucp_Dogra,+ ucp_Gunjala_Gondi,+ ucp_Hanifi_Rohingya,+ ucp_Makasar,+ ucp_Medefaidrin,+ ucp_Old_Sogdian,+ ucp_Sogdian,+ /* New for Unicode 12.0.0 */+ ucp_Elymaic,+ ucp_Nandinagari,+ ucp_Nyiakeng_Puachue_Hmong,+ ucp_Wancho,+ /* New for Unicode 13.0.0 */+ ucp_Chorasmian,+ ucp_Dives_Akuru,+ ucp_Khitan_Small_Script,+ ucp_Yezidi+};++#endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */++/* End of pcre2_ucp.h */
+ src/c/pcre2/src/pcre2_valid_utf.c view
@@ -0,0 +1,398 @@+/*************************************************+* 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) 2016-2020 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.+-----------------------------------------------------------------------------+*/+++/* This module contains an internal function for validating UTF character+strings. This file is also #included by the pcre2test program, which uses+macros to change names from _pcre2_xxx to xxxx, thereby avoiding name clashes+with the library. In this case, PCRE2_PCRE2TEST is defined. */++#ifndef PCRE2_PCRE2TEST /* We're compiling the library */+#ifdef HAVE_CONFIG_H+#include "config.h"+#endif+#include "pcre2_internal.h"+#endif /* PCRE2_PCRE2TEST */+++#ifndef SUPPORT_UNICODE+/*************************************************+* Dummy function when Unicode is not supported *+*************************************************/++/* This function should never be called when Unicode is not supported. */++int+PRIV(valid_utf)(PCRE2_SPTR string, PCRE2_SIZE length, PCRE2_SIZE *erroroffset)+{+(void)string;+(void)length;+(void)erroroffset;+return 0;+}+#else /* UTF is supported */++++/*************************************************+* Validate a UTF string *+*************************************************/++/* This function is called (optionally) at the start of compile or match, to+check that a supposed UTF string is actually valid. The early check means+that subsequent code can assume it is dealing with a valid string. The check+can be turned off for maximum performance, but the consequences of supplying an+invalid string are then undefined.++Arguments:+ string points to the string+ length length of string+ errp pointer to an error position offset variable++Returns: == 0 if the string is a valid UTF string+ != 0 otherwise, setting the offset of the bad character+*/++int+PRIV(valid_utf)(PCRE2_SPTR string, PCRE2_SIZE length, PCRE2_SIZE *erroroffset)+{+PCRE2_SPTR p;+uint32_t c;++/* ----------------- Check a UTF-8 string ----------------- */++#if PCRE2_CODE_UNIT_WIDTH == 8++/* Originally, this function checked according to RFC 2279, allowing for values+in the range 0 to 0x7fffffff, up to 6 bytes long, but ensuring that they were+in the canonical format. Once somebody had pointed out RFC 3629 to me (it+obsoletes 2279), additional restrictions were applied. The values are now+limited to be between 0 and 0x0010ffff, no more than 4 bytes long, and the+subrange 0xd000 to 0xdfff is excluded. However, the format of 5-byte and 6-byte+characters is still checked. Error returns are as follows:++PCRE2_ERROR_UTF8_ERR1 Missing 1 byte at the end of the string+PCRE2_ERROR_UTF8_ERR2 Missing 2 bytes at the end of the string+PCRE2_ERROR_UTF8_ERR3 Missing 3 bytes at the end of the string+PCRE2_ERROR_UTF8_ERR4 Missing 4 bytes at the end of the string+PCRE2_ERROR_UTF8_ERR5 Missing 5 bytes at the end of the string+PCRE2_ERROR_UTF8_ERR6 2nd-byte's two top bits are not 0x80+PCRE2_ERROR_UTF8_ERR7 3rd-byte's two top bits are not 0x80+PCRE2_ERROR_UTF8_ERR8 4th-byte's two top bits are not 0x80+PCRE2_ERROR_UTF8_ERR9 5th-byte's two top bits are not 0x80+PCRE2_ERROR_UTF8_ERR10 6th-byte's two top bits are not 0x80+PCRE2_ERROR_UTF8_ERR11 5-byte character is not permitted by RFC 3629+PCRE2_ERROR_UTF8_ERR12 6-byte character is not permitted by RFC 3629+PCRE2_ERROR_UTF8_ERR13 4-byte character with value > 0x10ffff is not permitted+PCRE2_ERROR_UTF8_ERR14 3-byte character with value 0xd800-0xdfff is not permitted+PCRE2_ERROR_UTF8_ERR15 Overlong 2-byte sequence+PCRE2_ERROR_UTF8_ERR16 Overlong 3-byte sequence+PCRE2_ERROR_UTF8_ERR17 Overlong 4-byte sequence+PCRE2_ERROR_UTF8_ERR18 Overlong 5-byte sequence (won't ever occur)+PCRE2_ERROR_UTF8_ERR19 Overlong 6-byte sequence (won't ever occur)+PCRE2_ERROR_UTF8_ERR20 Isolated 0x80 byte (not within UTF-8 character)+PCRE2_ERROR_UTF8_ERR21 Byte with the illegal value 0xfe or 0xff+*/++for (p = string; length > 0; p++)+ {+ uint32_t ab, d;++ c = *p;+ length--;++ if (c < 128) continue; /* ASCII character */++ if (c < 0xc0) /* Isolated 10xx xxxx byte */+ {+ *erroroffset = (PCRE2_SIZE)(p - string);+ return PCRE2_ERROR_UTF8_ERR20;+ }++ if (c >= 0xfe) /* Invalid 0xfe or 0xff bytes */+ {+ *erroroffset = (PCRE2_SIZE)(p - string);+ return PCRE2_ERROR_UTF8_ERR21;+ }++ ab = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes (1-5) */+ if (length < ab) /* Missing bytes */+ {+ *erroroffset = (PCRE2_SIZE)(p - string);+ switch(ab - length)+ {+ case 1: return PCRE2_ERROR_UTF8_ERR1;+ case 2: return PCRE2_ERROR_UTF8_ERR2;+ case 3: return PCRE2_ERROR_UTF8_ERR3;+ case 4: return PCRE2_ERROR_UTF8_ERR4;+ case 5: return PCRE2_ERROR_UTF8_ERR5;+ }+ }+ length -= ab; /* Length remaining */++ /* Check top bits in the second byte */++ if (((d = *(++p)) & 0xc0) != 0x80)+ {+ *erroroffset = (int)(p - string) - 1;+ return PCRE2_ERROR_UTF8_ERR6;+ }++ /* For each length, check that the remaining bytes start with the 0x80 bit+ set and not the 0x40 bit. Then check for an overlong sequence, and for the+ excluded range 0xd800 to 0xdfff. */++ switch (ab)+ {+ /* 2-byte character. No further bytes to check for 0x80. Check first byte+ for for xx00 000x (overlong sequence). */++ case 1: if ((c & 0x3e) == 0)+ {+ *erroroffset = (int)(p - string) - 1;+ return PCRE2_ERROR_UTF8_ERR15;+ }+ break;++ /* 3-byte character. Check third byte for 0x80. Then check first 2 bytes+ for 1110 0000, xx0x xxxx (overlong sequence) or+ 1110 1101, 1010 xxxx (0xd800 - 0xdfff) */++ case 2:+ if ((*(++p) & 0xc0) != 0x80) /* Third byte */+ {+ *erroroffset = (int)(p - string) - 2;+ return PCRE2_ERROR_UTF8_ERR7;+ }+ if (c == 0xe0 && (d & 0x20) == 0)+ {+ *erroroffset = (int)(p - string) - 2;+ return PCRE2_ERROR_UTF8_ERR16;+ }+ if (c == 0xed && d >= 0xa0)+ {+ *erroroffset = (int)(p - string) - 2;+ return PCRE2_ERROR_UTF8_ERR14;+ }+ break;++ /* 4-byte character. Check 3rd and 4th bytes for 0x80. Then check first 2+ bytes for for 1111 0000, xx00 xxxx (overlong sequence), then check for a+ character greater than 0x0010ffff (f4 8f bf bf) */++ case 3:+ if ((*(++p) & 0xc0) != 0x80) /* Third byte */+ {+ *erroroffset = (int)(p - string) - 2;+ return PCRE2_ERROR_UTF8_ERR7;+ }+ if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */+ {+ *erroroffset = (int)(p - string) - 3;+ return PCRE2_ERROR_UTF8_ERR8;+ }+ if (c == 0xf0 && (d & 0x30) == 0)+ {+ *erroroffset = (int)(p - string) - 3;+ return PCRE2_ERROR_UTF8_ERR17;+ }+ if (c > 0xf4 || (c == 0xf4 && d > 0x8f))+ {+ *erroroffset = (int)(p - string) - 3;+ return PCRE2_ERROR_UTF8_ERR13;+ }+ break;++ /* 5-byte and 6-byte characters are not allowed by RFC 3629, and will be+ rejected by the length test below. However, we do the appropriate tests+ here so that overlong sequences get diagnosed, and also in case there is+ ever an option for handling these larger code points. */++ /* 5-byte character. Check 3rd, 4th, and 5th bytes for 0x80. Then check for+ 1111 1000, xx00 0xxx */++ case 4:+ if ((*(++p) & 0xc0) != 0x80) /* Third byte */+ {+ *erroroffset = (int)(p - string) - 2;+ return PCRE2_ERROR_UTF8_ERR7;+ }+ if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */+ {+ *erroroffset = (int)(p - string) - 3;+ return PCRE2_ERROR_UTF8_ERR8;+ }+ if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */+ {+ *erroroffset = (int)(p - string) - 4;+ return PCRE2_ERROR_UTF8_ERR9;+ }+ if (c == 0xf8 && (d & 0x38) == 0)+ {+ *erroroffset = (int)(p - string) - 4;+ return PCRE2_ERROR_UTF8_ERR18;+ }+ break;++ /* 6-byte character. Check 3rd-6th bytes for 0x80. Then check for+ 1111 1100, xx00 00xx. */++ case 5:+ if ((*(++p) & 0xc0) != 0x80) /* Third byte */+ {+ *erroroffset = (int)(p - string) - 2;+ return PCRE2_ERROR_UTF8_ERR7;+ }+ if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */+ {+ *erroroffset = (int)(p - string) - 3;+ return PCRE2_ERROR_UTF8_ERR8;+ }+ if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */+ {+ *erroroffset = (int)(p - string) - 4;+ return PCRE2_ERROR_UTF8_ERR9;+ }+ if ((*(++p) & 0xc0) != 0x80) /* Sixth byte */+ {+ *erroroffset = (int)(p - string) - 5;+ return PCRE2_ERROR_UTF8_ERR10;+ }+ if (c == 0xfc && (d & 0x3c) == 0)+ {+ *erroroffset = (int)(p - string) - 5;+ return PCRE2_ERROR_UTF8_ERR19;+ }+ break;+ }++ /* Character is valid under RFC 2279, but 4-byte and 5-byte characters are+ excluded by RFC 3629. The pointer p is currently at the last byte of the+ character. */++ if (ab > 3)+ {+ *erroroffset = (int)(p - string) - ab;+ return (ab == 4)? PCRE2_ERROR_UTF8_ERR11 : PCRE2_ERROR_UTF8_ERR12;+ }+ }+return 0;+++/* ----------------- Check a UTF-16 string ----------------- */++#elif PCRE2_CODE_UNIT_WIDTH == 16++/* There's not so much work, nor so many errors, for UTF-16.+PCRE2_ERROR_UTF16_ERR1 Missing low surrogate at the end of the string+PCRE2_ERROR_UTF16_ERR2 Invalid low surrogate+PCRE2_ERROR_UTF16_ERR3 Isolated low surrogate+*/++for (p = string; length > 0; p++)+ {+ c = *p;+ length--;++ if ((c & 0xf800) != 0xd800)+ {+ /* Normal UTF-16 code point. Neither high nor low surrogate. */+ }+ else if ((c & 0x0400) == 0)+ {+ /* High surrogate. Must be a followed by a low surrogate. */+ if (length == 0)+ {+ *erroroffset = p - string;+ return PCRE2_ERROR_UTF16_ERR1;+ }+ p++;+ length--;+ if ((*p & 0xfc00) != 0xdc00)+ {+ *erroroffset = p - string - 1;+ return PCRE2_ERROR_UTF16_ERR2;+ }+ }+ else+ {+ /* Isolated low surrogate. Always an error. */+ *erroroffset = p - string;+ return PCRE2_ERROR_UTF16_ERR3;+ }+ }+return 0;++++/* ----------------- Check a UTF-32 string ----------------- */++#else++/* There is very little to do for a UTF-32 string.+PCRE2_ERROR_UTF32_ERR1 Surrogate character+PCRE2_ERROR_UTF32_ERR2 Character > 0x10ffff+*/++for (p = string; length > 0; length--, p++)+ {+ c = *p;+ if ((c & 0xfffff800u) != 0xd800u)+ {+ /* Normal UTF-32 code point. Neither high nor low surrogate. */+ if (c > 0x10ffffu)+ {+ *erroroffset = p - string;+ return PCRE2_ERROR_UTF32_ERR2;+ }+ }+ else+ {+ /* A surrogate */+ *erroroffset = p - string;+ return PCRE2_ERROR_UTF32_ERR1;+ }+ }+return 0;+#endif /* CODE_UNIT_WIDTH */+}+#endif /* SUPPORT_UNICODE */++/* End of pcre2_valid_utf.c */
+ src/c/pcre2/src/pcre2_xclass.c view
@@ -0,0 +1,271 @@+/*************************************************+* 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) 2016-2019 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.+-----------------------------------------------------------------------------+*/++/* This module contains an internal function that is used to match an extended+class. It is used by pcre2_auto_possessify() and by both pcre2_match() and+pcre2_def_match(). */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif+++#include "pcre2_internal.h"++/*************************************************+* Match character against an XCLASS *+*************************************************/++/* This function is called to match a character against an extended class that+might contain codepoints above 255 and/or Unicode properties.++Arguments:+ c the character+ data points to the flag code unit of the XCLASS data+ utf TRUE if in UTF mode++Returns: TRUE if character matches, else FALSE+*/++BOOL+PRIV(xclass)(uint32_t c, PCRE2_SPTR data, BOOL utf)+{+PCRE2_UCHAR t;+BOOL negated = (*data & XCL_NOT) != 0;++#if PCRE2_CODE_UNIT_WIDTH == 8+/* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */+utf = TRUE;+#endif++/* Code points < 256 are matched against a bitmap, if one is present. If not,+we still carry on, because there may be ranges that start below 256 in the+additional data. */++if (c < 256)+ {+ if ((*data & XCL_HASPROP) == 0)+ {+ if ((*data & XCL_MAP) == 0) return negated;+ return (((uint8_t *)(data + 1))[c/8] & (1u << (c&7))) != 0;+ }+ if ((*data & XCL_MAP) != 0 &&+ (((uint8_t *)(data + 1))[c/8] & (1u << (c&7))) != 0)+ return !negated; /* char found */+ }++/* First skip the bit map if present. Then match against the list of Unicode+properties or large chars or ranges that end with a large char. We won't ever+encounter XCL_PROP or XCL_NOTPROP when UTF support is not compiled. */++if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(PCRE2_UCHAR);++while ((t = *data++) != XCL_END)+ {+ uint32_t x, y;+ if (t == XCL_SINGLE)+ {+#ifdef SUPPORT_UNICODE+ if (utf)+ {+ GETCHARINC(x, data); /* macro generates multiple statements */+ }+ else+#endif+ x = *data++;+ if (c == x) return !negated;+ }+ else if (t == XCL_RANGE)+ {+#ifdef SUPPORT_UNICODE+ if (utf)+ {+ GETCHARINC(x, data); /* macro generates multiple statements */+ GETCHARINC(y, data); /* macro generates multiple statements */+ }+ else+#endif+ {+ x = *data++;+ y = *data++;+ }+ if (c >= x && c <= y) return !negated;+ }++#ifdef SUPPORT_UNICODE+ else /* XCL_PROP & XCL_NOTPROP */+ {+ const ucd_record *prop = GET_UCD(c);+ BOOL isprop = t == XCL_PROP;++ switch(*data)+ {+ case PT_ANY:+ if (isprop) return !negated;+ break;++ case PT_LAMP:+ if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||+ prop->chartype == ucp_Lt) == isprop) return !negated;+ break;++ case PT_GC:+ if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == isprop)+ return !negated;+ break;++ case PT_PC:+ if ((data[1] == prop->chartype) == isprop) return !negated;+ break;++ case PT_SC:+ if ((data[1] == prop->script) == isprop) return !negated;+ break;++ case PT_ALNUM:+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N) == isprop)+ return !negated;+ 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(c)+ {+ HSPACE_CASES:+ VSPACE_CASES:+ if (isprop) return !negated;+ break;++ default:+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == isprop)+ return !negated;+ break;+ }+ break;++ case PT_WORD:+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||+ PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE)+ == isprop)+ return !negated;+ break;++ case PT_UCNC:+ if (c < 0xa0)+ {+ if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||+ c == CHAR_GRAVE_ACCENT) == isprop)+ return !negated;+ }+ else+ {+ if ((c < 0xd800 || c > 0xdfff) == isprop)+ return !negated;+ }+ break;++ /* The following three properties can occur only in an XCLASS, as there+ is no \p or \P coding for them. */++ /* Graphic character. Implement this as not Z (space or separator) and+ not C (other), except for Cf (format) with a few exceptions. This seems+ to be what Perl does. The exceptional characters are:++ U+061C Arabic Letter Mark+ U+180E Mongolian Vowel Separator+ U+2066 - U+2069 Various "isolate"s+ */++ case PT_PXGRAPH:+ if ((PRIV(ucp_gentype)[prop->chartype] != ucp_Z &&+ (PRIV(ucp_gentype)[prop->chartype] != ucp_C ||+ (prop->chartype == ucp_Cf &&+ c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069))+ )) == isprop)+ return !negated;+ break;++ /* Printable character: same as graphic, with the addition of Zs, i.e.+ not Zl and not Zp, and U+180E. */++ case PT_PXPRINT:+ if ((prop->chartype != ucp_Zl &&+ prop->chartype != ucp_Zp &&+ (PRIV(ucp_gentype)[prop->chartype] != ucp_C ||+ (prop->chartype == ucp_Cf &&+ c != 0x061c && (c < 0x2066 || c > 0x2069))+ )) == isprop)+ return !negated;+ break;++ /* Punctuation: all Unicode punctuation, plus ASCII characters that+ Unicode treats as symbols rather than punctuation, for Perl+ compatibility (these are $+<=>^`|~). */++ case PT_PXPUNCT:+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_P ||+ (c < 128 && PRIV(ucp_gentype)[prop->chartype] == ucp_S)) == isprop)+ return !negated;+ break;++ /* This should never occur, but compilers may mutter if there is no+ default. */++ default:+ return FALSE;+ }++ data += 2;+ }+#else+ (void)utf; /* Avoid compiler warning */+#endif /* SUPPORT_UNICODE */+ }++return negated; /* char did not match */+}++/* End of pcre2_xclass.c */
+ src/c/pcre2/src/pcre2demo.c view
@@ -0,0 +1,494 @@+/*************************************************+* PCRE2 DEMONSTRATION PROGRAM *+*************************************************/++/* This is a demonstration program to illustrate a straightforward way of+using the PCRE2 regular expression library from a C program. See the+pcre2sample documentation for a short discussion ("man pcre2sample" if you have+the PCRE2 man pages installed). PCRE2 is a revised API for the library, and is+incompatible with the original PCRE API.++There are actually three libraries, each supporting a different code unit+width. This demonstration program uses the 8-bit library. The default is to+process each code unit as a separate character, but if the pattern begins with+"(*UTF)", both it and the subject are treated as UTF-8 strings, where+characters may occupy multiple code units.++In Unix-like environments, if PCRE2 is installed in your standard system+libraries, you should be able to compile this program using this command:++cc -Wall pcre2demo.c -lpcre2-8 -o pcre2demo++If PCRE2 is not installed in a standard place, it is likely to be installed+with support for the pkg-config mechanism. If you have pkg-config, you can+compile this program using this command:++cc -Wall pcre2demo.c `pkg-config --cflags --libs libpcre2-8` -o pcre2demo++If you do not have pkg-config, you may have to use something like this:++cc -Wall pcre2demo.c -I/usr/local/include -L/usr/local/lib \+ -R/usr/local/lib -lpcre2-8 -o pcre2demo++Replace "/usr/local/include" and "/usr/local/lib" with wherever the include and+library files for PCRE2 are installed on your system. Only some operating+systems (Solaris is one) use the -R option.++Building under Windows:++If you want to statically link this program against a non-dll .a file, you must+define PCRE2_STATIC before including pcre2.h, so in this environment, uncomment+the following line. */++/* #define PCRE2_STATIC */++/* The PCRE2_CODE_UNIT_WIDTH macro must be defined before including pcre2.h.+For a program that uses only one code unit width, setting it to 8, 16, or 32+makes it possible to use generic function names such as pcre2_compile(). Note+that just changing 8 to 16 (for example) is not sufficient to convert this+program to process 16-bit characters. Even in a fully 16-bit environment, where+string-handling functions such as strcmp() and printf() work with 16-bit+characters, the code for handling the table of named substrings will still need+to be modified. */++#define PCRE2_CODE_UNIT_WIDTH 8++#include <stdio.h>+#include <string.h>+#include <pcre2.h>+++/**************************************************************************+* Here is the program. The API includes the concept of "contexts" for *+* setting up unusual interface requirements for compiling and matching, *+* such as custom memory managers and non-standard newline definitions. *+* This program does not do any of this, so it makes no use of contexts, *+* always passing NULL where a context could be given. *+**************************************************************************/++int main(int argc, char **argv)+{+pcre2_code *re;+PCRE2_SPTR pattern; /* PCRE2_SPTR is a pointer to unsigned code units of */+PCRE2_SPTR subject; /* the appropriate width (in this case, 8 bits). */+PCRE2_SPTR name_table;++int crlf_is_newline;+int errornumber;+int find_all;+int i;+int rc;+int utf8;++uint32_t option_bits;+uint32_t namecount;+uint32_t name_entry_size;+uint32_t newline;++PCRE2_SIZE erroroffset;+PCRE2_SIZE *ovector;+PCRE2_SIZE subject_length;++pcre2_match_data *match_data;+++/**************************************************************************+* First, sort out the command line. There is only one possible option at *+* the moment, "-g" to request repeated matching to find all occurrences, *+* like Perl's /g option. We set the variable find_all to a non-zero value *+* if the -g option is present. *+**************************************************************************/++find_all = 0;+for (i = 1; i < argc; i++)+ {+ if (strcmp(argv[i], "-g") == 0) find_all = 1;+ else if (argv[i][0] == '-')+ {+ printf("Unrecognised option %s\n", argv[i]);+ return 1;+ }+ else break;+ }++/* After the options, we require exactly two arguments, which are the pattern,+and the subject string. */++if (argc - i != 2)+ {+ printf("Exactly two arguments required: a regex and a subject string\n");+ return 1;+ }++/* Pattern and subject are char arguments, so they can be straightforwardly+cast to PCRE2_SPTR because we are working in 8-bit code units. The subject+length is cast to PCRE2_SIZE for completeness, though PCRE2_SIZE is in fact+defined to be size_t. */++pattern = (PCRE2_SPTR)argv[i];+subject = (PCRE2_SPTR)argv[i+1];+subject_length = (PCRE2_SIZE)strlen((char *)subject);+++/*************************************************************************+* Now we are going to compile the regular expression pattern, and handle *+* any errors that are detected. *+*************************************************************************/++re = pcre2_compile(+ pattern, /* the pattern */+ PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */+ 0, /* default options */+ &errornumber, /* for error number */+ &erroroffset, /* for error offset */+ NULL); /* use default compile context */++/* Compilation failed: print the error message and exit. */++if (re == NULL)+ {+ PCRE2_UCHAR buffer[256];+ pcre2_get_error_message(errornumber, buffer, sizeof(buffer));+ printf("PCRE2 compilation failed at offset %d: %s\n", (int)erroroffset,+ buffer);+ return 1;+ }+++/*************************************************************************+* If the compilation succeeded, we call PCRE2 again, in order to do a *+* pattern match against the subject string. This does just ONE match. If *+* further matching is needed, it will be done below. Before running the *+* match we must set up a match_data block for holding the result. Using *+* pcre2_match_data_create_from_pattern() ensures that the block is *+* exactly the right size for the number of capturing parentheses in the *+* pattern. If you need to know the actual size of a match_data block as *+* a number of bytes, you can find it like this: *+* *+* PCRE2_SIZE match_data_size = pcre2_get_match_data_size(match_data); *+*************************************************************************/++match_data = pcre2_match_data_create_from_pattern(re, NULL);++/* Now run the match. */++rc = pcre2_match(+ re, /* the compiled pattern */+ subject, /* the subject string */+ subject_length, /* the length of the subject */+ 0, /* start at offset 0 in the subject */+ 0, /* default options */+ match_data, /* block for storing the result */+ NULL); /* use default match context */++/* Matching failed: handle error cases */++if (rc < 0)+ {+ switch(rc)+ {+ case PCRE2_ERROR_NOMATCH: printf("No match\n"); break;+ /*+ Handle other special cases if you like+ */+ default: printf("Matching error %d\n", rc); break;+ }+ pcre2_match_data_free(match_data); /* Release memory used for the match */+ pcre2_code_free(re); /* data and the compiled pattern. */+ return 1;+ }++/* Match succeded. Get a pointer to the output vector, where string offsets are+stored. */++ovector = pcre2_get_ovector_pointer(match_data);+printf("Match succeeded at offset %d\n", (int)ovector[0]);+++/*************************************************************************+* We have found the first match within the subject string. If the output *+* vector wasn't big enough, say so. Then output any substrings that were *+* captured. *+*************************************************************************/++/* The output vector wasn't big enough. This should not happen, because we used+pcre2_match_data_create_from_pattern() above. */++if (rc == 0)+ printf("ovector was not big enough for all the captured substrings\n");++/* We must guard against patterns such as /(?=.\K)/ that use \K in an assertion+to set the start of a match later than its end. In this demonstration program,+we just detect this case and give up. */++if (ovector[0] > ovector[1])+ {+ printf("\\K was used in an assertion to set the match start after its end.\n"+ "From end to start the match was: %.*s\n", (int)(ovector[0] - ovector[1]),+ (char *)(subject + ovector[1]));+ printf("Run abandoned\n");+ pcre2_match_data_free(match_data);+ pcre2_code_free(re);+ return 1;+ }++/* Show substrings stored in the output vector by number. Obviously, in a real+application you might want to do things other than print them. */++for (i = 0; i < rc; i++)+ {+ PCRE2_SPTR substring_start = subject + ovector[2*i];+ PCRE2_SIZE substring_length = ovector[2*i+1] - ovector[2*i];+ printf("%2d: %.*s\n", i, (int)substring_length, (char *)substring_start);+ }+++/**************************************************************************+* That concludes the basic part of this demonstration program. We have *+* compiled a pattern, and performed a single match. The code that follows *+* shows first how to access named substrings, and then how to code for *+* repeated matches on the same subject. *+**************************************************************************/++/* See if there are any named substrings, and if so, show them by name. First+we have to extract the count of named parentheses from the pattern. */++(void)pcre2_pattern_info(+ re, /* the compiled pattern */+ PCRE2_INFO_NAMECOUNT, /* get the number of named substrings */+ &namecount); /* where to put the answer */++if (namecount == 0) printf("No named substrings\n"); else+ {+ PCRE2_SPTR tabptr;+ printf("Named substrings\n");++ /* Before we can access the substrings, we must extract the table for+ translating names to numbers, and the size of each entry in the table. */++ (void)pcre2_pattern_info(+ re, /* the compiled pattern */+ PCRE2_INFO_NAMETABLE, /* address of the table */+ &name_table); /* where to put the answer */++ (void)pcre2_pattern_info(+ re, /* the compiled pattern */+ PCRE2_INFO_NAMEENTRYSIZE, /* size of each entry in the table */+ &name_entry_size); /* where to put the answer */++ /* Now we can scan the table and, for each entry, print the number, the name,+ and the substring itself. In the 8-bit library the number is held in two+ bytes, most significant first. */++ tabptr = name_table;+ for (i = 0; i < namecount; i++)+ {+ int n = (tabptr[0] << 8) | tabptr[1];+ printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2,+ (int)(ovector[2*n+1] - ovector[2*n]), subject + ovector[2*n]);+ tabptr += name_entry_size;+ }+ }+++/*************************************************************************+* If the "-g" option was given on the command line, we want to continue *+* to search for additional matches in the subject string, in a similar *+* way to the /g option in Perl. This turns out to be trickier than you *+* might think because of the possibility of matching an empty string. *+* What happens is as follows: *+* *+* If the previous match was NOT for an empty string, we can just start *+* the next match at the end of the previous one. *+* *+* If the previous match WAS for an empty string, we can't do that, as it *+* would lead to an infinite loop. Instead, a call of pcre2_match() is *+* made with the PCRE2_NOTEMPTY_ATSTART and PCRE2_ANCHORED flags set. The *+* first of these tells PCRE2 that an empty string at the start of the *+* subject is not a valid match; other possibilities must be tried. The *+* second flag restricts PCRE2 to one match attempt at the initial string *+* position. If this match succeeds, an alternative to the empty string *+* match has been found, and we can print it and proceed round the loop, *+* advancing by the length of whatever was found. If this match does not *+* succeed, we still stay in the loop, advancing by just one character. *+* In UTF-8 mode, which can be set by (*UTF) in the pattern, this may be *+* more than one byte. *+* *+* However, there is a complication concerned with newlines. When the *+* newline convention is such that CRLF is a valid newline, we must *+* advance by two characters rather than one. The newline convention can *+* be set in the regex by (*CR), etc.; if not, we must find the default. *+*************************************************************************/++if (!find_all) /* Check for -g */+ {+ pcre2_match_data_free(match_data); /* Release the memory that was used */+ pcre2_code_free(re); /* for the match data and the pattern. */+ return 0; /* Exit the program. */+ }++/* Before running the loop, check for UTF-8 and whether CRLF is a valid newline+sequence. First, find the options with which the regex was compiled and extract+the UTF state. */++(void)pcre2_pattern_info(re, PCRE2_INFO_ALLOPTIONS, &option_bits);+utf8 = (option_bits & PCRE2_UTF) != 0;++/* Now find the newline convention and see whether CRLF is a valid newline+sequence. */++(void)pcre2_pattern_info(re, PCRE2_INFO_NEWLINE, &newline);+crlf_is_newline = newline == PCRE2_NEWLINE_ANY ||+ newline == PCRE2_NEWLINE_CRLF ||+ newline == PCRE2_NEWLINE_ANYCRLF;++/* Loop for second and subsequent matches */++for (;;)+ {+ uint32_t options = 0; /* Normally no options */+ PCRE2_SIZE start_offset = ovector[1]; /* Start at end of previous match */++ /* If the previous match was for an empty string, we are finished if we are+ at the end of the subject. Otherwise, arrange to run another match at the+ same point to see if a non-empty match can be found. */++ if (ovector[0] == ovector[1])+ {+ if (ovector[0] == subject_length) break;+ options = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;+ }++ /* If the previous match was not an empty string, there is one tricky case to+ consider. If a pattern contains \K within a lookbehind assertion at the+ start, the end of the matched string can be at the offset where the match+ started. Without special action, this leads to a loop that keeps on matching+ the same substring. We must detect this case and arrange to move the start on+ by one character. The pcre2_get_startchar() function returns the starting+ offset that was passed to pcre2_match(). */++ else+ {+ PCRE2_SIZE startchar = pcre2_get_startchar(match_data);+ if (start_offset <= startchar)+ {+ if (startchar >= subject_length) break; /* Reached end of subject. */+ start_offset = startchar + 1; /* Advance by one character. */+ if (utf8) /* If UTF-8, it may be more */+ { /* than one code unit. */+ for (; start_offset < subject_length; start_offset++)+ if ((subject[start_offset] & 0xc0) != 0x80) break;+ }+ }+ }++ /* Run the next matching operation */++ rc = pcre2_match(+ re, /* the compiled pattern */+ subject, /* the subject string */+ subject_length, /* the length of the subject */+ start_offset, /* starting offset in the subject */+ options, /* options */+ match_data, /* block for storing the result */+ NULL); /* use default match context */++ /* This time, a result of NOMATCH isn't an error. If the value in "options"+ is zero, it just means we have found all possible matches, so the loop ends.+ Otherwise, it means we have failed to find a non-empty-string match at a+ point where there was a previous empty-string match. In this case, we do what+ Perl does: advance the matching position by one character, and continue. We+ do this by setting the "end of previous match" offset, because that is picked+ up at the top of the loop as the point at which to start again.++ There are two complications: (a) When CRLF is a valid newline sequence, and+ the current position is just before it, advance by an extra byte. (b)+ Otherwise we must ensure that we skip an entire UTF character if we are in+ UTF mode. */++ if (rc == PCRE2_ERROR_NOMATCH)+ {+ if (options == 0) break; /* All matches found */+ ovector[1] = start_offset + 1; /* Advance one code unit */+ if (crlf_is_newline && /* If CRLF is a newline & */+ start_offset < subject_length - 1 && /* we are at CRLF, */+ subject[start_offset] == '\r' &&+ subject[start_offset + 1] == '\n')+ ovector[1] += 1; /* Advance by one more. */+ else if (utf8) /* Otherwise, ensure we */+ { /* advance a whole UTF-8 */+ while (ovector[1] < subject_length) /* character. */+ {+ if ((subject[ovector[1]] & 0xc0) != 0x80) break;+ ovector[1] += 1;+ }+ }+ continue; /* Go round the loop again */+ }++ /* Other matching errors are not recoverable. */++ if (rc < 0)+ {+ printf("Matching error %d\n", rc);+ pcre2_match_data_free(match_data);+ pcre2_code_free(re);+ return 1;+ }++ /* Match succeded */++ printf("\nMatch succeeded again at offset %d\n", (int)ovector[0]);++ /* The match succeeded, but the output vector wasn't big enough. This+ should not happen. */++ if (rc == 0)+ printf("ovector was not big enough for all the captured substrings\n");++ /* We must guard against patterns such as /(?=.\K)/ that use \K in an+ assertion to set the start of a match later than its end. In this+ demonstration program, we just detect this case and give up. */++ if (ovector[0] > ovector[1])+ {+ printf("\\K was used in an assertion to set the match start after its end.\n"+ "From end to start the match was: %.*s\n", (int)(ovector[0] - ovector[1]),+ (char *)(subject + ovector[1]));+ printf("Run abandoned\n");+ pcre2_match_data_free(match_data);+ pcre2_code_free(re);+ return 1;+ }++ /* As before, show substrings stored in the output vector by number, and then+ also any named substrings. */++ for (i = 0; i < rc; i++)+ {+ PCRE2_SPTR substring_start = subject + ovector[2*i];+ size_t substring_length = ovector[2*i+1] - ovector[2*i];+ printf("%2d: %.*s\n", i, (int)substring_length, (char *)substring_start);+ }++ if (namecount == 0) printf("No named substrings\n"); else+ {+ PCRE2_SPTR tabptr = name_table;+ printf("Named substrings\n");+ for (i = 0; i < namecount; i++)+ {+ int n = (tabptr[0] << 8) | tabptr[1];+ printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2,+ (int)(ovector[2*n+1] - ovector[2*n]), subject + ovector[2*n]);+ tabptr += name_entry_size;+ }+ }+ } /* End of loop to find second and subsequent matches */++printf("\n");+pcre2_match_data_free(match_data);+pcre2_code_free(re);+return 0;+}++/* End of pcre2demo.c */
+ src/c/pcre2/src/pcre2grep.c view
@@ -0,0 +1,4553 @@+/*************************************************+* pcre2grep program *+*************************************************/++/* This is a grep program that uses the 8-bit PCRE regular expression library+via the PCRE2 updated API to do its pattern matching. On Unix-like, Windows,+and native z/OS systems it can recurse into directories, and in z/OS it can+handle PDS files.++Note that for native z/OS, in addition to defining the NATIVE_ZOS macro, an+additional header is required. That header is not included in the main PCRE2+distribution because other apparatus is needed to compile pcre2grep for z/OS.+The header can be found in the special z/OS distribution, which is available+from www.zaconsultants.net or from www.cbttape.org.++ Copyright (c) 1997-2020 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++#include <ctype.h>+#include <locale.h>+#include <stdio.h>+#include <string.h>+#include <stdlib.h>+#include <errno.h>++#include <sys/types.h>+#include <sys/stat.h>++#if (defined _WIN32 || (defined HAVE_WINDOWS_H && HAVE_WINDOWS_H)) \+ && !defined WIN32 && !defined(__CYGWIN__)+#define WIN32+#endif++/* Some cmake's define it still */+#if defined(__CYGWIN__) && defined(WIN32)+#undef WIN32+#endif++#ifdef __VMS+#include clidef+#include descrip+#include lib$routines+#endif++#ifdef WIN32+#include <io.h> /* For _setmode() */+#include <fcntl.h> /* For _O_BINARY */+#endif++#if defined(SUPPORT_PCRE2GREP_CALLOUT) && defined(SUPPORT_PCRE2GREP_CALLOUT_FORK)+#ifdef WIN32+#include <process.h>+#else+#include <sys/wait.h>+#endif+#endif++#ifdef HAVE_UNISTD_H+#include <unistd.h>+#endif++#ifdef SUPPORT_LIBZ+#include <zlib.h>+#endif++#ifdef SUPPORT_LIBBZ2+#include <bzlib.h>+#endif++#define PCRE2_CODE_UNIT_WIDTH 8+#include "pcre2.h"++/* Older versions of MSVC lack snprintf(). This define allows for+warning/error-free compilation and testing with MSVC compilers back to at least+MSVC 10/2010. Except for VC6 (which is missing some fundamentals and fails). */++#if defined(_MSC_VER) && (_MSC_VER < 1900)+#define snprintf _snprintf+#endif++/* VC and older compilers don't support %td or %zu, and even some that claim to+be C99 don't support it (hence DISABLE_PERCENT_ZT). */++#if defined(_MSC_VER) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L || defined(DISABLE_PERCENT_ZT)+#define PTR_FORM "lu"+#define SIZ_FORM "lu"+#define SIZ_CAST (unsigned long int)+#else+#define PTR_FORM "td"+#define SIZ_FORM "zu"+#define SIZ_CAST+#endif++#define FALSE 0+#define TRUE 1++typedef int BOOL;++#define DEFAULT_CAPTURE_MAX 50++#if BUFSIZ > 8192+#define MAXPATLEN BUFSIZ+#else+#define MAXPATLEN 8192+#endif++#define FNBUFSIZ 2048+#define ERRBUFSIZ 256++/* Values for the "filenames" variable, which specifies options for file name+output. The order is important; it is assumed that a file name is wanted for+all values greater than FN_DEFAULT. */++enum { FN_NONE, FN_DEFAULT, FN_MATCH_ONLY, FN_NOMATCH_ONLY, FN_FORCE };++/* File reading styles */++enum { FR_PLAIN, FR_LIBZ, FR_LIBBZ2 };++/* Actions for the -d and -D options */++enum { dee_READ, dee_SKIP, dee_RECURSE };+enum { DEE_READ, DEE_SKIP };++/* Actions for special processing options (flag bits) */++#define PO_WORD_MATCH 0x0001+#define PO_LINE_MATCH 0x0002+#define PO_FIXED_STRINGS 0x0004++/* Binary file options */++enum { BIN_BINARY, BIN_NOMATCH, BIN_TEXT };++/* Return values from decode_dollar_escape() */++enum { DDE_ERROR, DDE_CAPTURE, DDE_CHAR };++/* In newer versions of gcc, with FORTIFY_SOURCE set (the default in some+environments), a warning is issued if the value of fwrite() is ignored.+Unfortunately, casting to (void) does not suppress the warning. To get round+this, we use a macro that compiles a fudge. Oddly, this does not also seem to+apply to fprintf(). */++#define FWRITE_IGNORE(a,b,c,d) if (fwrite(a,b,c,d)) {}++/* Under Windows, we have to set stdout to be binary, so that it does not+convert \r\n at the ends of output lines to \r\r\n. However, that means that+any messages written to stdout must have \r\n as their line terminator. This is+handled by using STDOUT_NL as the newline string. We also use a normal double+quote for the example, as single quotes aren't usually available. */++#ifdef WIN32+#define STDOUT_NL "\r\n"+#define STDOUT_NL_LEN 2+#define QUOT "\""+#else+#define STDOUT_NL "\n"+#define STDOUT_NL_LEN 1+#define QUOT "'"+#endif++/* This code is returned from decode_dollar_escape() when $n is encountered,+and used to mean "output STDOUT_NL". It is, of course, not a valid Unicode code+point. */++#define STDOUT_NL_CODE 0x7fffffffu++++/*************************************************+* Global variables *+*************************************************/++/* Jeffrey Friedl has some debugging requirements that are not part of the+regular code. */++#ifdef JFRIEDL_DEBUG+static int S_arg = -1;+static unsigned int jfriedl_XR = 0; /* repeat regex attempt this many times */+static unsigned int jfriedl_XT = 0; /* replicate text this many times */+static const char *jfriedl_prefix = "";+static const char *jfriedl_postfix = "";+#endif++static const char *colour_string = "1;31";+static const char *colour_option = NULL;+static const char *dee_option = NULL;+static const char *DEE_option = NULL;+static const char *locale = NULL;+static const char *newline_arg = NULL;+static const char *om_separator = NULL;+static const char *stdin_name = "(standard input)";+static const char *output_text = NULL;++static char *main_buffer = NULL;++static int after_context = 0;+static int before_context = 0;+static int binary_files = BIN_BINARY;+static int both_context = 0;+static int bufthird = PCRE2GREP_BUFSIZE;+static int max_bufthird = PCRE2GREP_MAX_BUFSIZE;+static int bufsize = 3*PCRE2GREP_BUFSIZE;+static int endlinetype;++static int count_limit = -1; /* Not long, so that it works with OP_NUMBER */+static unsigned long int counts_printed = 0;+static unsigned long int total_count = 0;++#ifdef WIN32+static int dee_action = dee_SKIP;+#else+static int dee_action = dee_READ;+#endif++static int DEE_action = DEE_READ;+static int error_count = 0;+static int filenames = FN_DEFAULT;++#ifdef SUPPORT_PCRE2GREP_JIT+static BOOL use_jit = TRUE;+#else+static BOOL use_jit = FALSE;+#endif++static const uint8_t *character_tables = NULL;++static uint32_t pcre2_options = 0;+static uint32_t extra_options = 0;+static PCRE2_SIZE heap_limit = PCRE2_UNSET;+static uint32_t match_limit = 0;+static uint32_t depth_limit = 0;++static pcre2_compile_context *compile_context;+static pcre2_match_context *match_context;+static pcre2_match_data *match_data;+static PCRE2_SIZE *offsets;+static uint32_t offset_size;+static uint32_t capture_max = DEFAULT_CAPTURE_MAX;++static BOOL count_only = FALSE;+static BOOL do_colour = FALSE;+#ifdef WIN32+static BOOL do_ansi = FALSE;+#endif+static BOOL file_offsets = FALSE;+static BOOL hyphenpending = FALSE;+static BOOL invert = FALSE;+static BOOL line_buffered = FALSE;+static BOOL line_offsets = FALSE;+static BOOL multiline = FALSE;+static BOOL number = FALSE;+static BOOL omit_zero_count = FALSE;+static BOOL resource_error = FALSE;+static BOOL quiet = FALSE;+static BOOL show_total_count = FALSE;+static BOOL silent = FALSE;+static BOOL utf = FALSE;++static uint8_t utf8_buffer[8];+++/* Structure for list of --only-matching capturing numbers. */++typedef struct omstr {+ struct omstr *next;+ int groupnum;+} omstr;++static omstr *only_matching = NULL;+static omstr *only_matching_last = NULL;+static int only_matching_count;++/* Structure for holding the two variables that describe a number chain. */++typedef struct omdatastr {+ omstr **anchor;+ omstr **lastptr;+} omdatastr;++static omdatastr only_matching_data = { &only_matching, &only_matching_last };++/* Structure for list of file names (for -f and --{in,ex}clude-from) */++typedef struct fnstr {+ struct fnstr *next;+ char *name;+} fnstr;++static fnstr *exclude_from = NULL;+static fnstr *exclude_from_last = NULL;+static fnstr *include_from = NULL;+static fnstr *include_from_last = NULL;++static fnstr *file_lists = NULL;+static fnstr *file_lists_last = NULL;+static fnstr *pattern_files = NULL;+static fnstr *pattern_files_last = NULL;++/* Structure for holding the two variables that describe a file name chain. */++typedef struct fndatastr {+ fnstr **anchor;+ fnstr **lastptr;+} fndatastr;++static fndatastr exclude_from_data = { &exclude_from, &exclude_from_last };+static fndatastr include_from_data = { &include_from, &include_from_last };+static fndatastr file_lists_data = { &file_lists, &file_lists_last };+static fndatastr pattern_files_data = { &pattern_files, &pattern_files_last };++/* Structure for pattern and its compiled form; used for matching patterns and+also for include/exclude patterns. */++typedef struct patstr {+ struct patstr *next;+ char *string;+ PCRE2_SIZE length;+ pcre2_code *compiled;+} patstr;++static patstr *patterns = NULL;+static patstr *patterns_last = NULL;+static patstr *include_patterns = NULL;+static patstr *include_patterns_last = NULL;+static patstr *exclude_patterns = NULL;+static patstr *exclude_patterns_last = NULL;+static patstr *include_dir_patterns = NULL;+static patstr *include_dir_patterns_last = NULL;+static patstr *exclude_dir_patterns = NULL;+static patstr *exclude_dir_patterns_last = NULL;++/* Structure holding the two variables that describe a pattern chain. A pointer+to such structures is used for each appropriate option. */++typedef struct patdatastr {+ patstr **anchor;+ patstr **lastptr;+} patdatastr;++static patdatastr match_patdata = { &patterns, &patterns_last };+static patdatastr include_patdata = { &include_patterns, &include_patterns_last };+static patdatastr exclude_patdata = { &exclude_patterns, &exclude_patterns_last };+static patdatastr include_dir_patdata = { &include_dir_patterns, &include_dir_patterns_last };+static patdatastr exclude_dir_patdata = { &exclude_dir_patterns, &exclude_dir_patterns_last };++static patstr **incexlist[4] = { &include_patterns, &exclude_patterns,+ &include_dir_patterns, &exclude_dir_patterns };++static const char *incexname[4] = { "--include", "--exclude",+ "--include-dir", "--exclude-dir" };++/* Structure for options and list of them */++enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_U32NUMBER, OP_SIZE,+ OP_OP_NUMBER, OP_OP_NUMBERS, OP_PATLIST, OP_FILELIST, OP_BINFILES };++typedef struct option_item {+ int type;+ int one_char;+ void *dataptr;+ const char *long_name;+ const char *help_text;+} option_item;++/* Options without a single-letter equivalent get a negative value. This can be+used to identify them. */++#define N_COLOUR (-1)+#define N_EXCLUDE (-2)+#define N_EXCLUDE_DIR (-3)+#define N_HELP (-4)+#define N_INCLUDE (-5)+#define N_INCLUDE_DIR (-6)+#define N_LABEL (-7)+#define N_LOCALE (-8)+#define N_NULL (-9)+#define N_LOFFSETS (-10)+#define N_FOFFSETS (-11)+#define N_LBUFFER (-12)+#define N_H_LIMIT (-13)+#define N_M_LIMIT (-14)+#define N_M_LIMIT_DEP (-15)+#define N_BUFSIZE (-16)+#define N_NOJIT (-17)+#define N_FILE_LIST (-18)+#define N_BINARY_FILES (-19)+#define N_EXCLUDE_FROM (-20)+#define N_INCLUDE_FROM (-21)+#define N_OM_SEPARATOR (-22)+#define N_MAX_BUFSIZE (-23)+#define N_OM_CAPTURE (-24)++static option_item optionlist[] = {+ { OP_NODATA, N_NULL, NULL, "", "terminate options" },+ { OP_NODATA, N_HELP, NULL, "help", "display this help and exit" },+ { OP_NUMBER, 'A', &after_context, "after-context=number", "set number of following context lines" },+ { OP_NODATA, 'a', NULL, "text", "treat binary files as text" },+ { OP_NUMBER, 'B', &before_context, "before-context=number", "set number of prior context lines" },+ { OP_BINFILES, N_BINARY_FILES, NULL, "binary-files=word", "set treatment of binary files" },+ { OP_NUMBER, N_BUFSIZE,&bufthird, "buffer-size=number", "set processing buffer starting size" },+ { OP_NUMBER, N_MAX_BUFSIZE,&max_bufthird, "max-buffer-size=number", "set processing buffer maximum size" },+ { OP_OP_STRING, N_COLOUR, &colour_option, "color=option", "matched text color option" },+ { OP_OP_STRING, N_COLOUR, &colour_option, "colour=option", "matched text colour option" },+ { OP_NUMBER, 'C', &both_context, "context=number", "set number of context lines, before & after" },+ { OP_NODATA, 'c', NULL, "count", "print only a count of matching lines per FILE" },+ { OP_STRING, 'D', &DEE_option, "devices=action","how to handle devices, FIFOs, and sockets" },+ { OP_STRING, 'd', &dee_option, "directories=action", "how to handle directories" },+ { OP_PATLIST, 'e', &match_patdata, "regex(p)=pattern", "specify pattern (may be used more than once)" },+ { OP_NODATA, 'F', NULL, "fixed-strings", "patterns are sets of newline-separated strings" },+ { OP_FILELIST, 'f', &pattern_files_data, "file=path", "read patterns from file" },+ { OP_FILELIST, N_FILE_LIST, &file_lists_data, "file-list=path","read files to search from file" },+ { OP_NODATA, N_FOFFSETS, NULL, "file-offsets", "output file offsets, not text" },+ { OP_NODATA, 'H', NULL, "with-filename", "force the prefixing filename on output" },+ { OP_NODATA, 'h', NULL, "no-filename", "suppress the prefixing filename on output" },+ { OP_NODATA, 'I', NULL, "", "treat binary files as not matching (ignore)" },+ { OP_NODATA, 'i', NULL, "ignore-case", "ignore case distinctions" },+ { OP_NODATA, 'l', NULL, "files-with-matches", "print only FILE names containing matches" },+ { OP_NODATA, 'L', NULL, "files-without-match","print only FILE names not containing matches" },+ { OP_STRING, N_LABEL, &stdin_name, "label=name", "set name for standard input" },+ { OP_NODATA, N_LBUFFER, NULL, "line-buffered", "use line buffering" },+ { OP_NODATA, N_LOFFSETS, NULL, "line-offsets", "output line numbers and offsets, not text" },+ { OP_STRING, N_LOCALE, &locale, "locale=locale", "use the named locale" },+ { OP_SIZE, N_H_LIMIT, &heap_limit, "heap-limit=number", "set PCRE2 heap limit option (kibibytes)" },+ { OP_U32NUMBER, N_M_LIMIT, &match_limit, "match-limit=number", "set PCRE2 match limit option" },+ { OP_U32NUMBER, N_M_LIMIT_DEP, &depth_limit, "depth-limit=number", "set PCRE2 depth limit option" },+ { OP_U32NUMBER, N_M_LIMIT_DEP, &depth_limit, "recursion-limit=number", "obsolete synonym for depth-limit" },+ { OP_NODATA, 'M', NULL, "multiline", "run in multiline mode" },+ { OP_NUMBER, 'm', &count_limit, "max-count=number", "stop after <number> matched lines" },+ { OP_STRING, 'N', &newline_arg, "newline=type", "set newline type (CR, LF, CRLF, ANYCRLF, ANY, or NUL)" },+ { OP_NODATA, 'n', NULL, "line-number", "print line number with output lines" },+#ifdef SUPPORT_PCRE2GREP_JIT+ { OP_NODATA, N_NOJIT, NULL, "no-jit", "do not use just-in-time compiler optimization" },+#else+ { OP_NODATA, N_NOJIT, NULL, "no-jit", "ignored: this pcre2grep does not support JIT" },+#endif+ { OP_STRING, 'O', &output_text, "output=text", "show only this text (possibly expanded)" },+ { OP_OP_NUMBERS, 'o', &only_matching_data, "only-matching=n", "show only the part of the line that matched" },+ { OP_STRING, N_OM_SEPARATOR, &om_separator, "om-separator=text", "set separator for multiple -o output" },+ { OP_U32NUMBER, N_OM_CAPTURE, &capture_max, "om-capture=n", "set capture count for --only-matching" },+ { OP_NODATA, 'q', NULL, "quiet", "suppress output, just set return code" },+ { OP_NODATA, 'r', NULL, "recursive", "recursively scan sub-directories" },+ { OP_PATLIST, N_EXCLUDE,&exclude_patdata, "exclude=pattern","exclude matching files when recursing" },+ { OP_PATLIST, N_INCLUDE,&include_patdata, "include=pattern","include matching files when recursing" },+ { OP_PATLIST, N_EXCLUDE_DIR,&exclude_dir_patdata, "exclude-dir=pattern","exclude matching directories when recursing" },+ { OP_PATLIST, N_INCLUDE_DIR,&include_dir_patdata, "include-dir=pattern","include matching directories when recursing" },+ { OP_FILELIST, N_EXCLUDE_FROM,&exclude_from_data, "exclude-from=path", "read exclude list from file" },+ { OP_FILELIST, N_INCLUDE_FROM,&include_from_data, "include-from=path", "read include list from file" },+#ifdef JFRIEDL_DEBUG+ { OP_OP_NUMBER, 'S', &S_arg, "jeffS", "replace matched (sub)string with X" },+#endif+ { OP_NODATA, 's', NULL, "no-messages", "suppress error messages" },+ { OP_NODATA, 't', NULL, "total-count", "print total count of matching lines" },+ { OP_NODATA, 'u', NULL, "utf", "use UTF mode" },+ { OP_NODATA, 'U', NULL, "utf-allow-invalid", "use UTF mode, allow for invalid code units" },+ { OP_NODATA, 'V', NULL, "version", "print version information and exit" },+ { OP_NODATA, 'v', NULL, "invert-match", "select non-matching lines" },+ { OP_NODATA, 'w', NULL, "word-regex(p)", "force patterns to match only as words" },+ { OP_NODATA, 'x', NULL, "line-regex(p)", "force patterns to match only whole lines" },+ { OP_NODATA, 0, NULL, NULL, NULL }+};++/* Table of names for newline types. Must be kept in step with the definitions+of PCRE2_NEWLINE_xx in pcre2.h. */++static const char *newlines[] = {+ "DEFAULT", "CR", "LF", "CRLF", "ANY", "ANYCRLF", "NUL" };++/* UTF-8 tables */++const int utf8_table1[] =+ { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};+const int utf8_table1_size = sizeof(utf8_table1) / sizeof(int);++const int utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};+const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};++const char utf8_table4[] = {+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,+ 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };+++#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)+/*************************************************+* Emulated memmove() for systems without it *+*************************************************/++/* This function can make use of bcopy() if it is available. Otherwise do it by+steam, as there are some non-Unix environments that lack both memmove() and+bcopy(). */++static void *+emulated_memmove(void *d, const void *s, size_t n)+{+#ifdef HAVE_BCOPY+bcopy(s, d, n);+return d;+#else+size_t i;+unsigned char *dest = (unsigned char *)d;+const unsigned char *src = (const unsigned char *)s;+if (dest > src)+ {+ dest += n;+ src += n;+ for (i = 0; i < n; ++i) *(--dest) = *(--src);+ return (void *)dest;+ }+else+ {+ for (i = 0; i < n; ++i) *dest++ = *src++;+ return (void *)(dest - n);+ }+#endif /* not HAVE_BCOPY */+}+#undef memmove+#define memmove(d,s,n) emulated_memmove(d,s,n)+#endif /* not VPCOMPAT && not HAVE_MEMMOVE */++++/*************************************************+* Convert code point to UTF-8 *+*************************************************/++/* A static buffer is used. Returns the number of bytes. */++static int+ord2utf8(uint32_t value)+{+int i, j;+uint8_t *utf8bytes = utf8_buffer;+for (i = 0; i < utf8_table1_size; i++)+ if (value <= (uint32_t)utf8_table1[i]) break;+utf8bytes += i;+for (j = i; j > 0; j--)+ {+ *utf8bytes-- = 0x80 | (value & 0x3f);+ value >>= 6;+ }+*utf8bytes = utf8_table2[i] | value;+return i + 1;+}++++/*************************************************+* Case-independent string compare *+*************************************************/++static int+strcmpic(const char *str1, const char *str2)+{+unsigned int c1, c2;+while (*str1 != '\0' || *str2 != '\0')+ {+ c1 = tolower(*str1++);+ c2 = tolower(*str2++);+ if (c1 != c2) return ((c1 > c2) << 1) - 1;+ }+return 0;+}+++/*************************************************+* Parse GREP_COLORS *+*************************************************/++/* Extract ms or mt from GREP_COLORS.++Argument: the string, possibly NULL+Returns: the value of ms or mt, or NULL if neither present+*/++static char *+parse_grep_colors(const char *gc)+{+static char seq[16];+char *col;+uint32_t len;+if (gc == NULL) return NULL;+col = strstr(gc, "ms=");+if (col == NULL) col = strstr(gc, "mt=");+if (col == NULL) return NULL;+len = 0;+col += 3;+while (*col != ':' && *col != 0 && len < sizeof(seq)-1)+ seq[len++] = *col++;+seq[len] = 0;+return seq;+}+++/*************************************************+* Exit from the program *+*************************************************/++/* If there has been a resource error, give a suitable message.++Argument: the return code+Returns: does not return+*/++static void+pcre2grep_exit(int rc)+{+/* VMS does exit codes differently: both exit(1) and exit(0) return with a+status of 1, which is not helpful. To help with this problem, define a symbol+(akin to an environment variable) called "PCRE2GREP_RC" and put the exit code+therein. */++#ifdef __VMS+ char val_buf[4];+ $DESCRIPTOR(sym_nam, "PCRE2GREP_RC");+ $DESCRIPTOR(sym_val, val_buf);+ sprintf(val_buf, "%d", rc);+ sym_val.dsc$w_length = strlen(val_buf);+ lib$set_symbol(&sym_nam, &sym_val);+#endif++if (resource_error)+ {+ fprintf(stderr, "pcre2grep: Error %d, %d, %d or %d means that a resource "+ "limit was exceeded.\n", PCRE2_ERROR_JIT_STACKLIMIT, PCRE2_ERROR_MATCHLIMIT,+ PCRE2_ERROR_DEPTHLIMIT, PCRE2_ERROR_HEAPLIMIT);+ fprintf(stderr, "pcre2grep: Check your regex for nested unlimited loops.\n");+ }+exit(rc);+}+++/*************************************************+* Add item to chain of patterns *+*************************************************/++/* Used to add an item onto a chain, or just return an unconnected item if the+"after" argument is NULL.++Arguments:+ s pattern string to add+ patlen length of pattern+ after if not NULL points to item to insert after++Returns: new pattern block or NULL on error+*/++static patstr *+add_pattern(char *s, PCRE2_SIZE patlen, patstr *after)+{+patstr *p = (patstr *)malloc(sizeof(patstr));+if (p == NULL)+ {+ fprintf(stderr, "pcre2grep: malloc failed\n");+ pcre2grep_exit(2);+ }+if (patlen > MAXPATLEN)+ {+ fprintf(stderr, "pcre2grep: pattern is too long (limit is %d bytes)\n",+ MAXPATLEN);+ free(p);+ return NULL;+ }+p->next = NULL;+p->string = s;+p->length = patlen;+p->compiled = NULL;++if (after != NULL)+ {+ p->next = after->next;+ after->next = p;+ }+return p;+}+++/*************************************************+* Free chain of patterns *+*************************************************/++/* Used for several chains of patterns.++Argument: pointer to start of chain+Returns: nothing+*/++static void+free_pattern_chain(patstr *pc)+{+while (pc != NULL)+ {+ patstr *p = pc;+ pc = p->next;+ if (p->compiled != NULL) pcre2_code_free(p->compiled);+ free(p);+ }+}+++/*************************************************+* Free chain of file names *+*************************************************/++/*+Argument: pointer to start of chain+Returns: nothing+*/++static void+free_file_chain(fnstr *fn)+{+while (fn != NULL)+ {+ fnstr *f = fn;+ fn = f->next;+ free(f);+ }+}+++/*************************************************+* OS-specific functions *+*************************************************/++/* These definitions are needed in all Windows environments, even those where+Unix-style directory scanning can be used (see below). */++#ifdef WIN32++#ifndef STRICT+# define STRICT+#endif+#ifndef WIN32_LEAN_AND_MEAN+# define WIN32_LEAN_AND_MEAN+#endif++#include <windows.h>++#define iswild(name) (strpbrk(name, "*?") != NULL)++/* Convert ANSI BGR format to RGB used by Windows */+#define BGR_RGB(x) ((x & 1 ? 4 : 0) | (x & 2) | (x & 4 ? 1 : 0))++static HANDLE hstdout;+static CONSOLE_SCREEN_BUFFER_INFO csbi;+static WORD match_colour;++static WORD+decode_ANSI_colour(const char *cs)+{+WORD result = csbi.wAttributes;+while (*cs)+ {+ if (isdigit(*cs))+ {+ int code = atoi(cs);+ if (code == 1) result |= 0x08;+ else if (code == 4) result |= 0x8000;+ else if (code == 5) result |= 0x80;+ else if (code >= 30 && code <= 37) result = (result & 0xF8) | BGR_RGB(code - 30);+ else if (code == 39) result = (result & 0xF0) | (csbi.wAttributes & 0x0F);+ else if (code >= 40 && code <= 47) result = (result & 0x8F) | (BGR_RGB(code - 40) << 4);+ else if (code == 49) result = (result & 0x0F) | (csbi.wAttributes & 0xF0);+ /* aixterm high intensity colour codes */+ else if (code >= 90 && code <= 97) result = (result & 0xF0) | BGR_RGB(code - 90) | 0x08;+ else if (code >= 100 && code <= 107) result = (result & 0x0F) | (BGR_RGB(code - 100) << 4) | 0x80;++ while (isdigit(*cs)) cs++;+ }+ if (*cs) cs++;+ }+return result;+}+++static void+init_colour_output()+{+if (do_colour)+ {+ hstdout = GetStdHandle(STD_OUTPUT_HANDLE);+ /* This fails when redirected to con; try again if so. */+ if (!GetConsoleScreenBufferInfo(hstdout, &csbi) && !do_ansi)+ {+ HANDLE hcon = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,+ FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);+ GetConsoleScreenBufferInfo(hcon, &csbi);+ CloseHandle(hcon);+ }+ match_colour = decode_ANSI_colour(colour_string);+ /* No valid colour found - turn off colouring */+ if (!match_colour) do_colour = FALSE;+ }+}++#endif /* WIN32 */+++/* The following sets of functions are defined so that they can be made system+specific. At present there are versions for Unix-style environments, Windows,+native z/OS, and "no support". */+++/************* Directory scanning Unix-style and z/OS ***********/++#if (defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H) || defined NATIVE_ZOS+#include <sys/types.h>+#include <sys/stat.h>+#include <dirent.h>++#if defined NATIVE_ZOS+/************* Directory and PDS/E scanning for z/OS ***********/+/************* z/OS looks mostly like Unix with USS ************/+/* However, z/OS needs the #include statements in this header */+#include "pcrzosfs.h"+/* That header is not included in the main PCRE distribution because+ other apparatus is needed to compile pcre2grep for z/OS. The header+ can be found in the special z/OS distribution, which is available+ from www.zaconsultants.net or from www.cbttape.org. */+#endif++typedef DIR directory_type;+#define FILESEP '/'++static int+isdirectory(char *filename)+{+struct stat statbuf;+if (stat(filename, &statbuf) < 0)+ return 0; /* In the expectation that opening as a file will fail */+return S_ISDIR(statbuf.st_mode);+}++static directory_type *+opendirectory(char *filename)+{+return opendir(filename);+}++static char *+readdirectory(directory_type *dir)+{+for (;;)+ {+ struct dirent *dent = readdir(dir);+ if (dent == NULL) return NULL;+ if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)+ return dent->d_name;+ }+/* Control never reaches here */+}++static void+closedirectory(directory_type *dir)+{+closedir(dir);+}+++/************* Test for regular file, Unix-style **********/++static int+isregfile(char *filename)+{+struct stat statbuf;+if (stat(filename, &statbuf) < 0)+ return 1; /* In the expectation that opening as a file will fail */+return S_ISREG(statbuf.st_mode);+}+++#if defined NATIVE_ZOS+/************* Test for a terminal in z/OS **********/+/* isatty() does not work in a TSO environment, so always give FALSE.*/++static BOOL+is_stdout_tty(void)+{+return FALSE;+}++static BOOL+is_file_tty(FILE *f)+{+return FALSE;+}+++/************* Test for a terminal, Unix-style **********/++#else+static BOOL+is_stdout_tty(void)+{+return isatty(fileno(stdout));+}++static BOOL+is_file_tty(FILE *f)+{+return isatty(fileno(f));+}+#endif+++/************* Print optionally coloured match Unix-style and z/OS **********/++static void+print_match(const void *buf, int length)+{+if (length == 0) return;+if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);+FWRITE_IGNORE(buf, 1, length, stdout);+if (do_colour) fprintf(stdout, "%c[0m", 0x1b);+}++/* End of Unix-style or native z/OS environment functions. */+++/************* Directory scanning in Windows ***********/++/* I (Philip Hazel) have no means of testing this code. It was contributed by+Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES+when it did not exist. David Byron added a patch that moved the #include of+<windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.+*/++#elif defined WIN32++#ifndef INVALID_FILE_ATTRIBUTES+#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF+#endif++typedef struct directory_type+{+HANDLE handle;+BOOL first;+WIN32_FIND_DATA data;+} directory_type;++#define FILESEP '/'++int+isdirectory(char *filename)+{+DWORD attr = GetFileAttributes(filename);+if (attr == INVALID_FILE_ATTRIBUTES)+ return 0;+return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;+}++directory_type *+opendirectory(char *filename)+{+size_t len;+char *pattern;+directory_type *dir;+DWORD err;+len = strlen(filename);+pattern = (char *)malloc(len + 3);+dir = (directory_type *)malloc(sizeof(*dir));+if ((pattern == NULL) || (dir == NULL))+ {+ fprintf(stderr, "pcre2grep: malloc failed\n");+ pcre2grep_exit(2);+ }+memcpy(pattern, filename, len);+if (iswild(filename))+ pattern[len] = 0;+else+ memcpy(&(pattern[len]), "\\*", 3);+dir->handle = FindFirstFile(pattern, &(dir->data));+if (dir->handle != INVALID_HANDLE_VALUE)+ {+ free(pattern);+ dir->first = TRUE;+ return dir;+ }+err = GetLastError();+free(pattern);+free(dir);+errno = (err == ERROR_ACCESS_DENIED) ? EACCES : ENOENT;+return NULL;+}++char *+readdirectory(directory_type *dir)+{+for (;;)+ {+ if (!dir->first)+ {+ if (!FindNextFile(dir->handle, &(dir->data)))+ return NULL;+ }+ else+ {+ dir->first = FALSE;+ }+ if (strcmp(dir->data.cFileName, ".") != 0 && strcmp(dir->data.cFileName, "..") != 0)+ return dir->data.cFileName;+ }+#ifndef _MSC_VER+return NULL; /* Keep compiler happy; never executed */+#endif+}++void+closedirectory(directory_type *dir)+{+FindClose(dir->handle);+free(dir);+}+++/************* Test for regular file in Windows **********/++/* I don't know how to do this, or if it can be done; assume all paths are+regular if they are not directories. */++int isregfile(char *filename)+{+return !isdirectory(filename);+}+++/************* Test for a terminal in Windows **********/++static BOOL+is_stdout_tty(void)+{+return _isatty(_fileno(stdout));+}++static BOOL+is_file_tty(FILE *f)+{+return _isatty(_fileno(f));+}+++/************* Print optionally coloured match in Windows **********/++static void+print_match(const void *buf, int length)+{+if (length == 0) return;+if (do_colour)+ {+ if (do_ansi) fprintf(stdout, "%c[%sm", 0x1b, colour_string);+ else SetConsoleTextAttribute(hstdout, match_colour);+ }+FWRITE_IGNORE(buf, 1, length, stdout);+if (do_colour)+ {+ if (do_ansi) fprintf(stdout, "%c[0m", 0x1b);+ else SetConsoleTextAttribute(hstdout, csbi.wAttributes);+ }+}++/* End of Windows functions */+++/************* Directory scanning when we can't do it ***********/++/* The type is void, and apart from isdirectory(), the functions do nothing. */++#else++#define FILESEP 0+typedef void directory_type;++int isdirectory(char *filename) { return 0; }+directory_type * opendirectory(char *filename) { return (directory_type*)0;}+char *readdirectory(directory_type *dir) { return (char*)0;}+void closedirectory(directory_type *dir) {}+++/************* Test for regular file when we can't do it **********/++/* Assume all files are regular. */++int isregfile(char *filename) { return 1; }+++/************* Test for a terminal when we can't do it **********/++static BOOL+is_stdout_tty(void)+{+return FALSE;+}++static BOOL+is_file_tty(FILE *f)+{+return FALSE;+}+++/************* Print optionally coloured match when we can't do it **********/++static void+print_match(const void *buf, int length)+{+if (length == 0) return;+FWRITE_IGNORE(buf, 1, length, stdout);+}++#endif /* End of system-specific functions */++++#ifndef HAVE_STRERROR+/*************************************************+* Provide strerror() for non-ANSI libraries *+*************************************************/++/* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror()+in their libraries, but can provide the same facility by this simple+alternative function. */++extern int sys_nerr;+extern char *sys_errlist[];++char *+strerror(int n)+{+if (n < 0 || n >= sys_nerr) return "unknown error number";+return sys_errlist[n];+}+#endif /* HAVE_STRERROR */++++/*************************************************+* Usage function *+*************************************************/++static int+usage(int rc)+{+option_item *op;+fprintf(stderr, "Usage: pcre2grep [-");+for (op = optionlist; op->one_char != 0; op++)+ {+ if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);+ }+fprintf(stderr, "] [long options] [pattern] [files]\n");+fprintf(stderr, "Type \"pcre2grep --help\" for more information and the long "+ "options.\n");+return rc;+}++++/*************************************************+* Help function *+*************************************************/++static void+help(void)+{+option_item *op;++printf("Usage: pcre2grep [OPTION]... [PATTERN] [FILE1 FILE2 ...]" STDOUT_NL);+printf("Search for PATTERN in each FILE or standard input." STDOUT_NL);+printf("PATTERN must be present if neither -e nor -f is used." STDOUT_NL);++#ifdef SUPPORT_PCRE2GREP_CALLOUT+#ifdef SUPPORT_PCRE2GREP_CALLOUT_FORK+printf("All callout scripts in patterns are supported." STDOUT_NL);+#else+printf("Non-fork callout scripts in patterns are supported." STDOUT_NL);+#endif+#else+printf("Callout scripts are not supported in this pcre2grep." STDOUT_NL);+#endif++printf("\"-\" can be used as a file name to mean STDIN." STDOUT_NL);++#ifdef SUPPORT_LIBZ+printf("Files whose names end in .gz are read using zlib." STDOUT_NL);+#endif++#ifdef SUPPORT_LIBBZ2+printf("Files whose names end in .bz2 are read using bzlib2." STDOUT_NL);+#endif++#if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2+printf("Other files and the standard input are read as plain files." STDOUT_NL STDOUT_NL);+#else+printf("All files are read as plain files, without any interpretation." STDOUT_NL STDOUT_NL);+#endif++printf("Example: pcre2grep -i " QUOT "hello.*world" QUOT " menu.h main.c" STDOUT_NL STDOUT_NL);+printf("Options:" STDOUT_NL);++for (op = optionlist; op->one_char != 0; op++)+ {+ int n;+ char s[4];++ if (op->one_char > 0 && (op->long_name)[0] == 0)+ n = 31 - printf(" -%c", op->one_char);+ else+ {+ if (op->one_char > 0) sprintf(s, "-%c,", op->one_char);+ else strcpy(s, " ");+ n = 31 - printf(" %s --%s", s, op->long_name);+ }++ if (n < 1) n = 1;+ printf("%.*s%s" STDOUT_NL, n, " ", op->help_text);+ }++printf(STDOUT_NL "Numbers may be followed by K or M, e.g. --max-buffer-size=100K." STDOUT_NL);+printf("The default value for --buffer-size is %d." STDOUT_NL, PCRE2GREP_BUFSIZE);+printf("The default value for --max-buffer-size is %d." STDOUT_NL, PCRE2GREP_MAX_BUFSIZE);+printf("When reading patterns or file names from a file, trailing white" STDOUT_NL);+printf("space is removed and blank lines are ignored." STDOUT_NL);+printf("The maximum size of any pattern is %d bytes." STDOUT_NL, MAXPATLEN);++printf(STDOUT_NL "With no FILEs, read standard input. If fewer than two FILEs given, assume -h." STDOUT_NL);+printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble." STDOUT_NL);+}++++/*************************************************+* Test exclude/includes *+*************************************************/++/* If any exclude pattern matches, the path is excluded. Otherwise, unless+there are no includes, the path must match an include pattern.++Arguments:+ path the path to be matched+ ip the chain of include patterns+ ep the chain of exclude patterns++Returns: TRUE if the path is not excluded+*/++static BOOL+test_incexc(char *path, patstr *ip, patstr *ep)+{+int plen = strlen((const char *)path);++for (; ep != NULL; ep = ep->next)+ {+ if (pcre2_match(ep->compiled, (PCRE2_SPTR)path, plen, 0, 0, match_data, NULL) >= 0)+ return FALSE;+ }++if (ip == NULL) return TRUE;++for (; ip != NULL; ip = ip->next)+ {+ if (pcre2_match(ip->compiled, (PCRE2_SPTR)path, plen, 0, 0, match_data, NULL) >= 0)+ return TRUE;+ }++return FALSE;+}++++/*************************************************+* Decode integer argument value *+*************************************************/++/* Integer arguments can be followed by K or M. Avoid the use of strtoul()+because SunOS4 doesn't have it. This is used only for unpicking arguments, so+just keep it simple.++Arguments:+ option_data the option data string+ op the option item (for error messages)+ longop TRUE if option given in long form++Returns: a long integer+*/++static long int+decode_number(char *option_data, option_item *op, BOOL longop)+{+unsigned long int n = 0;+char *endptr = option_data;+while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++;+while (isdigit((unsigned char)(*endptr)))+ n = n * 10 + (int)(*endptr++ - '0');+if (toupper(*endptr) == 'K')+ {+ n *= 1024;+ endptr++;+ }+else if (toupper(*endptr) == 'M')+ {+ n *= 1024*1024;+ endptr++;+ }++if (*endptr != 0) /* Error */+ {+ if (longop)+ {+ char *equals = strchr(op->long_name, '=');+ int nlen = (equals == NULL)? (int)strlen(op->long_name) :+ (int)(equals - op->long_name);+ fprintf(stderr, "pcre2grep: Malformed number \"%s\" after --%.*s\n",+ option_data, nlen, op->long_name);+ }+ else+ fprintf(stderr, "pcre2grep: Malformed number \"%s\" after -%c\n",+ option_data, op->one_char);+ pcre2grep_exit(usage(2));+ }++return n;+}++++/*************************************************+* Add item to a chain of numbers *+*************************************************/++/* Used to add an item onto a chain, or just return an unconnected item if the+"after" argument is NULL.++Arguments:+ n the number to add+ after if not NULL points to item to insert after++Returns: new number block+*/++static omstr *+add_number(int n, omstr *after)+{+omstr *om = (omstr *)malloc(sizeof(omstr));++if (om == NULL)+ {+ fprintf(stderr, "pcre2grep: malloc failed\n");+ pcre2grep_exit(2);+ }+om->next = NULL;+om->groupnum = n;++if (after != NULL)+ {+ om->next = after->next;+ after->next = om;+ }+return om;+}++++/*************************************************+* Read one line of input *+*************************************************/++/* Normally, input that is to be scanned is read using fread() (or gzread, or+BZ2_read) into a large buffer, so many lines may be read at once. However,+doing this for tty input means that no output appears until a lot of input has+been typed. Instead, tty input is handled line by line. We cannot use fgets()+for this, because it does not stop at a binary zero, and therefore there is no+way of telling how many characters it has read, because there may be binary+zeros embedded in the data. This function is also used for reading patterns+from files (the -f option).++Arguments:+ buffer the buffer to read into+ length the maximum number of characters to read+ f the file++Returns: the number of characters read, zero at end of file+*/++static PCRE2_SIZE+read_one_line(char *buffer, int length, FILE *f)+{+int c;+int yield = 0;+while ((c = fgetc(f)) != EOF)+ {+ buffer[yield++] = c;+ if (c == '\n' || yield >= length) break;+ }+return yield;+}++++/*************************************************+* Find end of line *+*************************************************/++/* The length of the endline sequence that is found is set via lenptr. This may+be zero at the very end of the file if there is no line-ending sequence there.++Arguments:+ p current position in line+ endptr end of available data+ lenptr where to put the length of the eol sequence++Returns: pointer after the last byte of the line,+ including the newline byte(s)+*/++static char *+end_of_line(char *p, char *endptr, int *lenptr)+{+switch(endlinetype)+ {+ default: /* Just in case */+ case PCRE2_NEWLINE_LF:+ while (p < endptr && *p != '\n') p++;+ if (p < endptr)+ {+ *lenptr = 1;+ return p + 1;+ }+ *lenptr = 0;+ return endptr;++ case PCRE2_NEWLINE_CR:+ while (p < endptr && *p != '\r') p++;+ if (p < endptr)+ {+ *lenptr = 1;+ return p + 1;+ }+ *lenptr = 0;+ return endptr;++ case PCRE2_NEWLINE_NUL:+ while (p < endptr && *p != '\0') p++;+ if (p < endptr)+ {+ *lenptr = 1;+ return p + 1;+ }+ *lenptr = 0;+ return endptr;++ case PCRE2_NEWLINE_CRLF:+ for (;;)+ {+ while (p < endptr && *p != '\r') p++;+ if (++p >= endptr)+ {+ *lenptr = 0;+ return endptr;+ }+ if (*p == '\n')+ {+ *lenptr = 2;+ return p + 1;+ }+ }+ break;++ case PCRE2_NEWLINE_ANYCRLF:+ while (p < endptr)+ {+ int extra = 0;+ int c = *((unsigned char *)p);++ if (utf && c >= 0xc0)+ {+ int gcii, gcss;+ extra = utf8_table4[c & 0x3f]; /* Number of additional bytes */+ gcss = 6*extra;+ c = (c & utf8_table3[extra]) << gcss;+ for (gcii = 1; gcii <= extra; gcii++)+ {+ gcss -= 6;+ c |= (p[gcii] & 0x3f) << gcss;+ }+ }++ p += 1 + extra;++ switch (c)+ {+ case '\n':+ *lenptr = 1;+ return p;++ case '\r':+ if (p < endptr && *p == '\n')+ {+ *lenptr = 2;+ p++;+ }+ else *lenptr = 1;+ return p;++ default:+ break;+ }+ } /* End of loop for ANYCRLF case */++ *lenptr = 0; /* Must have hit the end */+ return endptr;++ case PCRE2_NEWLINE_ANY:+ while (p < endptr)+ {+ int extra = 0;+ int c = *((unsigned char *)p);++ if (utf && c >= 0xc0)+ {+ int gcii, gcss;+ extra = utf8_table4[c & 0x3f]; /* Number of additional bytes */+ gcss = 6*extra;+ c = (c & utf8_table3[extra]) << gcss;+ for (gcii = 1; gcii <= extra; gcii++)+ {+ gcss -= 6;+ c |= (p[gcii] & 0x3f) << gcss;+ }+ }++ p += 1 + extra;++ switch (c)+ {+ case '\n': /* LF */+ case '\v': /* VT */+ case '\f': /* FF */+ *lenptr = 1;+ return p;++ case '\r': /* CR */+ if (p < endptr && *p == '\n')+ {+ *lenptr = 2;+ p++;+ }+ else *lenptr = 1;+ return p;++#ifndef EBCDIC+ case 0x85: /* Unicode NEL */+ *lenptr = utf? 2 : 1;+ return p;++ case 0x2028: /* Unicode LS */+ case 0x2029: /* Unicode PS */+ *lenptr = 3;+ return p;+#endif /* Not EBCDIC */++ default:+ break;+ }+ } /* End of loop for ANY case */++ *lenptr = 0; /* Must have hit the end */+ return endptr;+ } /* End of overall switch */+}++++/*************************************************+* Find start of previous line *+*************************************************/++/* This is called when looking back for before lines to print.++Arguments:+ p start of the subsequent line+ startptr start of available data++Returns: pointer to the start of the previous line+*/++static char *+previous_line(char *p, char *startptr)+{+switch(endlinetype)+ {+ default: /* Just in case */+ case PCRE2_NEWLINE_LF:+ p--;+ while (p > startptr && p[-1] != '\n') p--;+ return p;++ case PCRE2_NEWLINE_CR:+ p--;+ while (p > startptr && p[-1] != '\n') p--;+ return p;++ case PCRE2_NEWLINE_NUL:+ p--;+ while (p > startptr && p[-1] != '\0') p--;+ return p;++ case PCRE2_NEWLINE_CRLF:+ for (;;)+ {+ p -= 2;+ while (p > startptr && p[-1] != '\n') p--;+ if (p <= startptr + 1 || p[-2] == '\r') return p;+ }+ /* Control can never get here */++ case PCRE2_NEWLINE_ANY:+ case PCRE2_NEWLINE_ANYCRLF:+ if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--;+ if (utf) while ((*p & 0xc0) == 0x80) p--;++ while (p > startptr)+ {+ unsigned int c;+ char *pp = p - 1;++ if (utf)+ {+ int extra = 0;+ while ((*pp & 0xc0) == 0x80) pp--;+ c = *((unsigned char *)pp);+ if (c >= 0xc0)+ {+ int gcii, gcss;+ extra = utf8_table4[c & 0x3f]; /* Number of additional bytes */+ gcss = 6*extra;+ c = (c & utf8_table3[extra]) << gcss;+ for (gcii = 1; gcii <= extra; gcii++)+ {+ gcss -= 6;+ c |= (pp[gcii] & 0x3f) << gcss;+ }+ }+ }+ else c = *((unsigned char *)pp);++ if (endlinetype == PCRE2_NEWLINE_ANYCRLF) switch (c)+ {+ case '\n': /* LF */+ case '\r': /* CR */+ return p;++ default:+ break;+ }++ else switch (c)+ {+ case '\n': /* LF */+ case '\v': /* VT */+ case '\f': /* FF */+ case '\r': /* CR */+#ifndef EBCDIC+ case 0x85: /* Unicode NEL */+ case 0x2028: /* Unicode LS */+ case 0x2029: /* Unicode PS */+#endif /* Not EBCDIC */+ return p;++ default:+ break;+ }++ p = pp; /* Back one character */+ } /* End of loop for ANY case */++ return startptr; /* Hit start of data */+ } /* End of overall switch */+}++++/*************************************************+* Output newline at end *+*************************************************/++/* This function is called if the final line of a file has been written to+stdout, but it does not have a terminating newline.++Arguments: none+Returns: nothing+*/++static void+write_final_newline(void)+{+switch(endlinetype)+ {+ default: /* Just in case */+ case PCRE2_NEWLINE_LF:+ case PCRE2_NEWLINE_ANY:+ case PCRE2_NEWLINE_ANYCRLF:+ fprintf(stdout, "\n");+ break;++ case PCRE2_NEWLINE_CR:+ fprintf(stdout, "\r");+ break;++ case PCRE2_NEWLINE_CRLF:+ fprintf(stdout, "\r\n");+ break;++ case PCRE2_NEWLINE_NUL:+ fprintf(stdout, "%c", 0);+ break;+ }+}+++/*************************************************+* Print the previous "after" lines *+*************************************************/++/* This is called if we are about to lose said lines because of buffer filling,+and at the end of the file. The data in the line is written using fwrite() so+that a binary zero does not terminate it.++Arguments:+ lastmatchnumber the number of the last matching line, plus one+ lastmatchrestart where we restarted after the last match+ endptr end of available data+ printname filename for printing++Returns: nothing+*/++static void+do_after_lines(unsigned long int lastmatchnumber, char *lastmatchrestart,+ char *endptr, const char *printname)+{+if (after_context > 0 && lastmatchnumber > 0)+ {+ int count = 0;+ int ellength = 0;+ while (lastmatchrestart < endptr && count < after_context)+ {+ char *pp = end_of_line(lastmatchrestart, endptr, &ellength);+ if (ellength == 0 && pp == main_buffer + bufsize) break;+ if (printname != NULL) fprintf(stdout, "%s-", printname);+ if (number) fprintf(stdout, "%lu-", lastmatchnumber++);+ FWRITE_IGNORE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);+ lastmatchrestart = pp;+ count++;+ }++ /* If we have printed any lines, arrange for a hyphen separator if anything+ else follows. Also, if the last line is the final line in the file and it had+ no newline, add one. */++ if (count > 0)+ {+ hyphenpending = TRUE;+ if (ellength == 0 && lastmatchrestart >= endptr)+ write_final_newline();+ }+ }+}++++/*************************************************+* Apply patterns to subject till one matches *+*************************************************/++/* This function is called to run through all patterns, looking for a match. It+is used multiple times for the same subject when colouring is enabled, in order+to find all possible matches.++Arguments:+ matchptr the start of the subject+ length the length of the subject to match+ options options for pcre_exec+ startoffset where to start matching+ mrc address of where to put the result of pcre2_match()++Returns: TRUE if there was a match+ FALSE if there was no match+ invert if there was a non-fatal error+*/++static BOOL+match_patterns(char *matchptr, PCRE2_SIZE length, unsigned int options,+ PCRE2_SIZE startoffset, int *mrc)+{+int i;+PCRE2_SIZE slen = length;+patstr *p = patterns;+const char *msg = "this text:\n\n";++if (slen > 200)+ {+ slen = 200;+ msg = "text that starts:\n\n";+ }++for (i = 1; p != NULL; p = p->next, i++)+ {+ *mrc = pcre2_match(p->compiled, (PCRE2_SPTR)matchptr, (int)length,+ startoffset, options, match_data, match_context);+ if (*mrc >= 0) return TRUE;+ if (*mrc == PCRE2_ERROR_NOMATCH) continue;+ fprintf(stderr, "pcre2grep: pcre2_match() gave error %d while matching ", *mrc);+ if (patterns->next != NULL) fprintf(stderr, "pattern number %d to ", i);+ fprintf(stderr, "%s", msg);+ FWRITE_IGNORE(matchptr, 1, slen, stderr); /* In case binary zero included */+ fprintf(stderr, "\n\n");+ if (*mrc <= PCRE2_ERROR_UTF8_ERR1 &&+ *mrc >= PCRE2_ERROR_UTF8_ERR21)+ {+ unsigned char mbuffer[256];+ PCRE2_SIZE startchar = pcre2_get_startchar(match_data);+ (void)pcre2_get_error_message(*mrc, mbuffer, sizeof(mbuffer));+ fprintf(stderr, "%s at offset %" SIZ_FORM "\n\n", mbuffer,+ SIZ_CAST startchar);+ }+ if (*mrc == PCRE2_ERROR_MATCHLIMIT || *mrc == PCRE2_ERROR_DEPTHLIMIT ||+ *mrc == PCRE2_ERROR_HEAPLIMIT || *mrc == PCRE2_ERROR_JIT_STACKLIMIT)+ resource_error = TRUE;+ if (error_count++ > 20)+ {+ fprintf(stderr, "pcre2grep: Too many errors - abandoned.\n");+ pcre2grep_exit(2);+ }+ return invert; /* No more matching; don't show the line again */+ }++return FALSE; /* No match, no errors */+}++++/*************************************************+* Decode dollar escape sequence *+*************************************************/++/* Called from various places to decode $ escapes in output strings. The escape+sequences are as follows:++$<digits> or ${<digits>} returns a capture number. However, if callout is TRUE,+zero is never returned; '0' is substituted.++$a returns bell.+$b returns backspace.+$e returns escape.+$f returns form feed.+$n returns newline.+$r returns carriage return.+$t returns tab.+$v returns vertical tab.+$o<digits> returns the character represented by the given octal+ number; up to three digits are processed.+$o{<digits>} does the same, up to 7 digits, but gives an error for mode-invalid+ code points.+$x<digits> returns the character represented by the given hexadecimal+ number; up to two digits are processed.+$x{<digits} does the same, up to 6 digits, but gives an error for mode-invalid+ code points.+Any other character is substituted by itself. E.g: $$ is replaced by a single+dollar.++Arguments:+ begin the start of the whole string+ string points to the $+ callout TRUE if in a callout (inhibits error messages)+ value where to return a value+ last where to return pointer to the last used character++Returns: DDE_ERROR after a syntax error+ DDE_CAPTURE if *value is a capture number+ DDE_CHAR if *value is a character code+*/++static int+decode_dollar_escape(PCRE2_SPTR begin, PCRE2_SPTR string, BOOL callout,+ uint32_t *value, PCRE2_SPTR *last)+{+uint32_t c = 0;+int base = 10;+int dcount;+int rc = DDE_CHAR;+BOOL brace = FALSE;++switch (*(++string))+ {+ case 0: /* Syntax error: a character must be present after $. */+ if (!callout)+ fprintf(stderr, "pcre2grep: Error in output text at offset %d: %s\n",+ (int)(string - begin), "no character after $");+ *last = string;+ return DDE_ERROR;++ case '{':+ brace = TRUE;+ string++;+ if (!isdigit(*string)) /* Syntax error: a decimal number required. */+ {+ if (!callout)+ fprintf(stderr, "pcre2grep: Error in output text at offset %d: %s\n",+ (int)(string - begin), "decimal number expected");+ rc = DDE_ERROR;+ break;+ }++ /* Fall through */++ /* The maximum capture number is 65535, so any number greater than that will+ always be an unknown capture number. We just stop incrementing, in order to+ avoid overflow. */++ case '0': case '1': case '2': case '3': case '4':+ case '5': case '6': case '7': case '8': case '9':+ do+ {+ if (c <= 65535) c = c * 10 + (*string - '0');+ string++;+ }+ while (*string >= '0' && *string <= '9');+ string--; /* Point to last digit */++ /* In a callout, capture number 0 is not available. No error can be given,+ so just return the character '0'. */++ if (callout && c == 0)+ {+ *value = '0';+ }+ else+ {+ *value = c;+ rc = DDE_CAPTURE;+ }+ break;++ /* Limit octal numbers to 3 digits without braces, or up to 7 with braces,+ for valid Unicode code points. */++ case 'o':+ base = 8;+ string++;+ if (*string == '{')+ {+ brace = TRUE;+ string++;+ dcount = 7;+ }+ else dcount = 3;+ for (; dcount > 0; dcount--)+ {+ if (*string < '0' || *string > '7') break;+ c = c * 8 + (*string++ - '0');+ }+ *value = c;+ string--; /* Point to last digit */+ break;++ /* Limit hex numbers to 2 digits without braces, or up to 6 with braces,+ for valid Unicode code points. */++ case 'x':+ base = 16;+ string++;+ if (*string == '{')+ {+ brace = TRUE;+ string++;+ dcount = 6;+ }+ else dcount = 2;+ for (; dcount > 0; dcount--)+ {+ if (!isxdigit(*string)) break;+ if (*string >= '0' && *string <= '9')+ c = c *16 + *string++ - '0';+ else+ c = c * 16 + (*string++ | 0x20) - 'a' + 10;+ }+ *value = c;+ string--; /* Point to last digit */+ break;++ case 'a': *value = '\a'; break;+ case 'b': *value = '\b'; break;+#ifndef EBCDIC+ case 'e': *value = '\033'; break;+#else+ case 'e': *value = '\047'; break;+#endif+ case 'f': *value = '\f'; break;+ case 'n': *value = STDOUT_NL_CODE; break;+ case 'r': *value = '\r'; break;+ case 't': *value = '\t'; break;+ case 'v': *value = '\v'; break;++ default: *value = *string; break;+ }++if (brace)+ {+ c = string[1];+ if (c != '}')+ {+ rc = DDE_ERROR;+ if (!callout)+ {+ if ((base == 8 && c >= '0' && c <= '7') ||+ (base == 16 && isxdigit(c)))+ {+ fprintf(stderr, "pcre2grep: Error in output text at offset %d: "+ "too many %s digits\n", (int)(string - begin),+ (base == 8)? "octal" : "hex");+ }+ else+ {+ fprintf(stderr, "pcre2grep: Error in output text at offset %d: %s\n",+ (int)(string - begin), "missing closing brace");+ }+ }+ }+ else string++;+ }++/* Check maximum code point values, but take note of STDOUT_NL_CODE. */++if (rc == DDE_CHAR && *value != STDOUT_NL_CODE)+ {+ uint32_t max = utf? 0x0010ffffu : 0xffu;+ if (*value > max)+ {+ if (!callout) + fprintf(stderr, "pcre2grep: Error in output text at offset %d: "+ "code point greater than 0x%x is invalid\n", (int)(string - begin), max);+ rc = DDE_ERROR;+ }+ }++*last = string;+return rc;+}++++/*************************************************+* Check output text for errors *+*************************************************/++/* Called early, to get errors before doing anything for -O text; also called+from callouts to check before outputting.++Arguments:+ string an --output text string+ callout TRUE if in a callout (stops printing errors)++Returns: TRUE if OK, FALSE on error+*/++static BOOL+syntax_check_output_text(PCRE2_SPTR string, BOOL callout)+{+uint32_t value;+PCRE2_SPTR begin = string;++for (; *string != 0; string++)+ {+ if (*string == '$' &&+ decode_dollar_escape(begin, string, callout, &value, &string) == DDE_ERROR)+ return FALSE;+ }++return TRUE;+}+++/*************************************************+* Display output text *+*************************************************/++/* Display the output text, which is assumed to have already been syntax+checked. Output may contain escape sequences started by the dollar sign.++Arguments:+ string: the output text+ callout: TRUE for the builtin callout, FALSE for --output+ subject the start of the subject+ ovector: capture offsets+ capture_top: number of captures++Returns: TRUE if something was output, other than newline+ FALSE if nothing was output, or newline was last output+*/++static BOOL+display_output_text(PCRE2_SPTR string, BOOL callout, PCRE2_SPTR subject,+ PCRE2_SIZE *ovector, PCRE2_SIZE capture_top)+{+uint32_t value;+BOOL printed = FALSE;+PCRE2_SPTR begin = string;++for (; *string != 0; string++)+ {+ if (*string == '$')+ {+ switch(decode_dollar_escape(begin, string, callout, &value, &string))+ {+ case DDE_CHAR:+ if (value == STDOUT_NL_CODE)+ {+ fprintf(stdout, STDOUT_NL);+ printed = FALSE;+ continue;+ }+ break; /* Will print value */++ case DDE_CAPTURE:+ if (value < capture_top)+ {+ PCRE2_SIZE capturesize;+ value *= 2;+ capturesize = ovector[value + 1] - ovector[value];+ if (capturesize > 0)+ {+ print_match(subject + ovector[value], capturesize);+ printed = TRUE;+ }+ }+ continue;++ default: /* Should not occur */+ break;+ }+ }++ else value = *string; /* Not a $ escape */++ if (utf && value <= 127) fprintf(stdout, "%c", *string); else+ {+ int i;+ int n = ord2utf8(value);+ for (i = 0; i < n; i++) fputc(utf8_buffer[i], stdout);+ }++ printed = TRUE;+ }++return printed;+}+++#ifdef SUPPORT_PCRE2GREP_CALLOUT++/*************************************************+* Parse and execute callout scripts *+*************************************************/++/* If SUPPORT_PCRE2GREP_CALLOUT_FORK is defined, this function parses a callout+string block and executes the program specified by the string. The string is a+list of substrings separated by pipe characters. The first substring represents+the executable name, and the following substrings specify the arguments:++ program_name|param1|param2|...++Any substring (including the program name) can contain escape sequences+started by the dollar character. The escape sequences are substituted as+follows:++ $<digits> or ${<digits>} is replaced by the captured substring of the given+ decimal number, which must be greater than zero. If the number is greater+ than the number of capturing substrings, or if the capture is unset, the+ replacement is empty.++ Any other character is substituted by itself. E.g: $$ is replaced by a single+ dollar or $| replaced by a pipe character.++Alternatively, if string starts with pipe, the remainder is taken as an output+string, same as --output. This is the only form that is supported if+SUPPORT_PCRE2GREP_FORK is not defined. In this case, --om-separator is used to+separate each callout, defaulting to newline.++Example:++ echo -e "abcde\n12345" | pcre2grep \+ '(.)(..(.))(?C"/bin/echo|Arg1: [$1] [$2] [$3]|Arg2: $|${1}$| ($4)")()' -++ Output:++ Arg1: [a] [bcd] [d] Arg2: |a| ()+ abcde+ Arg1: [1] [234] [4] Arg2: |1| ()+ 12345++Arguments:+ blockptr the callout block++Returns: currently it always returns with 0+*/++static int+pcre2grep_callout(pcre2_callout_block *calloutptr, void *unused)+{+PCRE2_SIZE length = calloutptr->callout_string_length;+PCRE2_SPTR string = calloutptr->callout_string;+PCRE2_SPTR subject = calloutptr->subject;+PCRE2_SIZE *ovector = calloutptr->offset_vector;+PCRE2_SIZE capture_top = calloutptr->capture_top;++#ifdef SUPPORT_PCRE2GREP_CALLOUT_FORK+PCRE2_SIZE argsvectorlen = 2;+PCRE2_SIZE argslen = 1;+char *args;+char *argsptr;+char **argsvector;+char **argsvectorptr;+#ifndef WIN32+pid_t pid;+#endif+int result = 0;+#endif /* SUPPORT_PCRE2GREP_CALLOUT_FORK */++(void)unused; /* Avoid compiler warning */++/* Only callouts with strings are supported. */++if (string == NULL || length == 0) return 0;++/* If there's no command, output the remainder directly. */++if (*string == '|')+ {+ string++;+ if (!syntax_check_output_text(string, TRUE)) return 0;+ (void)display_output_text(string, TRUE, subject, ovector, capture_top);+ return 0;+ }++#ifndef SUPPORT_PCRE2GREP_CALLOUT_FORK+return 0;+#else++/* Checking syntax and compute the number of string fragments. Callout strings+are silently ignored in the event of a syntax error. */++while (length > 0)+ {+ if (*string == '|')+ {+ argsvectorlen++;+ if (argsvectorlen > 10000) return 0; /* Too many args */+ }++ else if (*string == '$')+ {+ uint32_t value;+ PCRE2_SPTR begin = string;++ switch (decode_dollar_escape(begin, string, TRUE, &value, &string))+ {+ case DDE_CAPTURE:+ if (value < capture_top)+ {+ value *= 2;+ argslen += ovector[value + 1] - ovector[value];+ }+ argslen--; /* Negate the effect of argslen++ below. */+ break;++ case DDE_CHAR:+ if (value == STDOUT_NL_CODE) argslen += STDOUT_NL_LEN - 1;+ else if (utf && value > 127) argslen += ord2utf8(value) - 1;+ break;++ default: /* Should not occur */+ case DDE_ERROR:+ return 0;+ }++ length -= (string - begin);+ }++ string++;+ length--;+ argslen++;+ }++/* Get memory for the argument vector and its strings. */++args = (char*)malloc(argslen);+if (args == NULL) return 0;++argsvector = (char**)malloc(argsvectorlen * sizeof(char*));+if (argsvector == NULL)+ {+ free(args);+ return 0;+ }++/* Now reprocess the string and set up the arguments. */++argsptr = args;+argsvectorptr = argsvector;+*argsvectorptr++ = argsptr;++length = calloutptr->callout_string_length;+string = calloutptr->callout_string;++while (length > 0)+ {+ if (*string == '|')+ {+ *argsptr++ = '\0';+ *argsvectorptr++ = argsptr;+ }++ else if (*string == '$')+ {+ uint32_t value;+ PCRE2_SPTR begin = string;++ switch (decode_dollar_escape(begin, string, TRUE, &value, &string))+ {+ case DDE_CAPTURE:+ if (value < capture_top)+ {+ PCRE2_SIZE capturesize;+ value *= 2;+ capturesize = ovector[value + 1] - ovector[value];+ memcpy(argsptr, subject + ovector[value], capturesize);+ argsptr += capturesize;+ }+ break;++ case DDE_CHAR:+ if (value == STDOUT_NL_CODE)+ {+ memcpy(argsptr, STDOUT_NL, STDOUT_NL_LEN);+ argsptr += STDOUT_NL_LEN; + } + else if (utf && value > 127)+ {+ int n = ord2utf8(value);+ memcpy(argsptr, utf8_buffer, n);+ argsptr += n;+ }+ else+ {+ *argsptr++ = value;+ }+ break;++ default: /* Even though this should not occur, the string having */+ case DDE_ERROR: /* been checked above, we need to include the free() */+ free(args); /* calls so that source checkers do not complain. */+ free(argsvector);+ return 0;+ }++ length -= (string - begin);+ }++ else *argsptr++ = *string;++ /* Advance along the string */++ string++;+ length--;+ }++*argsptr++ = '\0';+*argsvectorptr = NULL;++/* Running an external command is system-dependent. Handle Windows and VMS as+necessary, otherwise assume fork(). */++#ifdef WIN32+result = _spawnvp(_P_WAIT, argsvector[0], (const char * const *)argsvector);++#elif defined __VMS+ {+ char cmdbuf[500];+ short i = 0;+ int flags = CLI$M_NOCLISYM|CLI$M_NOLOGNAM|CLI$M_NOKEYPAD, status, retstat;+ $DESCRIPTOR(cmd, cmdbuf);++ cmdbuf[0] = 0;+ while (argsvector[i])+ {+ strcat(cmdbuf, argsvector[i]);+ strcat(cmdbuf, " ");+ i++;+ }+ cmd.dsc$w_length = strlen(cmdbuf) - 1;+ status = lib$spawn(&cmd, 0,0, &flags, 0,0, &retstat);+ if (!(status & 1)) result = 0;+ else result = retstat & 1 ? 0 : 1;+ }++#else /* Neither Windows nor VMS */+pid = fork();+if (pid == 0)+ {+ (void)execv(argsvector[0], argsvector);+ /* Control gets here if there is an error, e.g. a non-existent program */+ exit(1);+ }+else if (pid > 0)+ (void)waitpid(pid, &result, 0);+#endif /* End Windows/VMS/other handling */++free(args);+free(argsvector);++/* Currently negative return values are not supported, only zero (match+continues) or non-zero (match fails). */++return result != 0;+#endif /* SUPPORT_PCRE2GREP_CALLOUT_FORK */+}+#endif /* SUPPORT_PCRE2GREP_CALLOUT */++++/*************************************************+* Read a portion of the file into buffer *+*************************************************/++static int+fill_buffer(void *handle, int frtype, char *buffer, int length,+ BOOL input_line_buffered)+{+(void)frtype; /* Avoid warning when not used */++#ifdef SUPPORT_LIBZ+if (frtype == FR_LIBZ)+ return gzread((gzFile)handle, buffer, length);+else+#endif++#ifdef SUPPORT_LIBBZ2+if (frtype == FR_LIBBZ2)+ return BZ2_bzread((BZFILE *)handle, buffer, length);+else+#endif++return (input_line_buffered ?+ read_one_line(buffer, length, (FILE *)handle) :+ fread(buffer, 1, length, (FILE *)handle));+}++++/*************************************************+* Grep an individual file *+*************************************************/++/* This is called from grep_or_recurse() below. It uses a buffer that is three+times the value of bufthird. The matching point is never allowed to stray into+the top third of the buffer, thus keeping more of the file available for+context printing or for multiline scanning. For large files, the pointer will+be in the middle third most of the time, so the bottom third is available for+"before" context printing.++Arguments:+ handle the fopened FILE stream for a normal file+ the gzFile pointer when reading is via libz+ the BZFILE pointer when reading is via libbz2+ frtype FR_PLAIN, FR_LIBZ, or FR_LIBBZ2+ filename the file name or NULL (for errors)+ printname the file name if it is to be printed for each match+ or NULL if the file name is not to be printed+ it cannot be NULL if filenames[_nomatch]_only is set++Returns: 0 if there was at least one match+ 1 otherwise (no matches)+ 2 if an overlong line is encountered+ 3 if there is a read error on a .bz2 file+*/++static int+pcre2grep(void *handle, int frtype, const char *filename, const char *printname)+{+int rc = 1;+int filepos = 0;+unsigned long int linenumber = 1;+unsigned long int lastmatchnumber = 0;+unsigned long int count = 0;+long int count_matched_lines = 0;+char *lastmatchrestart = main_buffer;+char *ptr = main_buffer;+char *endptr;+PCRE2_SIZE bufflength;+BOOL binary = FALSE;+BOOL endhyphenpending = FALSE;+BOOL lines_printed = FALSE;+BOOL input_line_buffered = line_buffered;+FILE *in = NULL; /* Ensure initialized */++/* Do the first read into the start of the buffer and set up the pointer to end+of what we have. In the case of libz, a non-zipped .gz file will be read as a+plain file. However, if a .bz2 file isn't actually bzipped, the first read will+fail. */++if (frtype != FR_LIBZ && frtype != FR_LIBBZ2)+ {+ in = (FILE *)handle;+ if (is_file_tty(in)) input_line_buffered = TRUE;+ }+else input_line_buffered = FALSE;++bufflength = fill_buffer(handle, frtype, main_buffer, bufsize,+ input_line_buffered);++#ifdef SUPPORT_LIBBZ2+if (frtype == FR_LIBBZ2 && (int)bufflength < 0) return 2; /* Gotcha: bufflength is PCRE2_SIZE */+#endif++endptr = main_buffer + bufflength;++/* Unless binary-files=text, see if we have a binary file. This uses the same+rule as GNU grep, namely, a search for a binary zero byte near the start of the+file. However, when the newline convention is binary zero, we can't do this. */++if (binary_files != BIN_TEXT)+ {+ if (endlinetype != PCRE2_NEWLINE_NUL)+ binary = memchr(main_buffer, 0, (bufflength > 1024)? 1024 : bufflength)+ != NULL;+ if (binary && binary_files == BIN_NOMATCH) return 1;+ }++/* Loop while the current pointer is not at the end of the file. For large+files, endptr will be at the end of the buffer when we are in the middle of the+file, but ptr will never get there, because as soon as it gets over 2/3 of the+way, the buffer is shifted left and re-filled. */++while (ptr < endptr)+ {+ int endlinelength;+ int mrc = 0;+ unsigned int options = 0;+ BOOL match;+ BOOL line_matched = FALSE;+ char *t = ptr;+ PCRE2_SIZE length, linelength;+ PCRE2_SIZE startoffset = 0;++ /* If the -m option set a limit for the number of matched or non-matched+ lines, check it here. A limit of zero means that no matching is ever done.+ For stdin from a file, set the file position. */++ if (count_limit >= 0 && count_matched_lines >= count_limit)+ {+ if (frtype == FR_PLAIN && filename == stdin_name && !is_file_tty(handle))+ (void)fseek(handle, (long int)filepos, SEEK_SET);+ rc = (count_limit == 0)? 1 : 0;+ break;+ }++ /* At this point, ptr is at the start of a line. We need to find the length+ of the subject string to pass to pcre2_match(). In multiline mode, it is the+ length remainder of the data in the buffer. Otherwise, it is the length of+ the next line, excluding the terminating newline. After matching, we always+ advance by the length of the next line. In multiline mode the PCRE2_FIRSTLINE+ option is used for compiling, so that any match is constrained to be in the+ first line. */++ t = end_of_line(t, endptr, &endlinelength);+ linelength = t - ptr - endlinelength;+ length = multiline? (PCRE2_SIZE)(endptr - ptr) : linelength;++ /* Check to see if the line we are looking at extends right to the very end+ of the buffer without a line terminator. This means the line is too long to+ handle at the current buffer size. Until the buffer reaches its maximum size,+ try doubling it and reading more data. */++ if (endlinelength == 0 && t == main_buffer + bufsize)+ {+ if (bufthird < max_bufthird)+ {+ char *new_buffer;+ int new_bufthird = 2*bufthird;++ if (new_bufthird > max_bufthird) new_bufthird = max_bufthird;+ new_buffer = (char *)malloc(3*new_bufthird);++ if (new_buffer == NULL)+ {+ fprintf(stderr,+ "pcre2grep: line %lu%s%s is too long for the internal buffer\n"+ "pcre2grep: not enough memory to increase the buffer size to %d\n",+ linenumber,+ (filename == NULL)? "" : " of file ",+ (filename == NULL)? "" : filename,+ new_bufthird);+ return 2;+ }++ /* Copy the data and adjust pointers to the new buffer location. */++ memcpy(new_buffer, main_buffer, bufsize);+ bufthird = new_bufthird;+ bufsize = 3*bufthird;+ ptr = new_buffer + (ptr - main_buffer);+ lastmatchrestart = new_buffer + (lastmatchrestart - main_buffer);+ free(main_buffer);+ main_buffer = new_buffer;++ /* Read more data into the buffer and then try to find the line ending+ again. */++ bufflength += fill_buffer(handle, frtype, main_buffer + bufflength,+ bufsize - bufflength, input_line_buffered);+ endptr = main_buffer + bufflength;+ continue;+ }+ else+ {+ fprintf(stderr,+ "pcre2grep: line %lu%s%s is too long for the internal buffer\n"+ "pcre2grep: the maximum buffer size is %d\n"+ "pcre2grep: use the --max-buffer-size option to change it\n",+ linenumber,+ (filename == NULL)? "" : " of file ",+ (filename == NULL)? "" : filename,+ bufthird);+ return 2;+ }+ }++ /* Extra processing for Jeffrey Friedl's debugging. */++#ifdef JFRIEDL_DEBUG+ if (jfriedl_XT || jfriedl_XR)+ {+# include <sys/time.h>+# include <time.h>+ struct timeval start_time, end_time;+ struct timezone dummy;+ int i;++ if (jfriedl_XT)+ {+ unsigned long newlen = length * jfriedl_XT + strlen(jfriedl_prefix) + strlen(jfriedl_postfix);+ const char *orig = ptr;+ ptr = malloc(newlen + 1);+ if (!ptr) {+ printf("out of memory");+ pcre2grep_exit(2);+ }+ endptr = ptr;+ strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix);+ for (i = 0; i < jfriedl_XT; i++) {+ strncpy(endptr, orig, length);+ endptr += length;+ }+ strcpy(endptr, jfriedl_postfix); endptr += strlen(jfriedl_postfix);+ length = newlen;+ }++ if (gettimeofday(&start_time, &dummy) != 0)+ perror("bad gettimeofday");+++ for (i = 0; i < jfriedl_XR; i++)+ match = (pcre_exec(patterns->compiled, patterns->hint, ptr, length, 0,+ PCRE2_NOTEMPTY, offsets, offset_size) >= 0);++ if (gettimeofday(&end_time, &dummy) != 0)+ perror("bad gettimeofday");++ double delta = ((end_time.tv_sec + (end_time.tv_usec / 1000000.0))+ -+ (start_time.tv_sec + (start_time.tv_usec / 1000000.0)));++ printf("%s TIMER[%.4f]\n", match ? "MATCH" : "FAIL", delta);+ return 0;+ }+#endif++ /* We come back here after a match when only_matching_count is non-zero, in+ order to find any further matches in the same line. This applies to+ --only-matching, --file-offsets, and --line-offsets. */++ ONLY_MATCHING_RESTART:++ /* Run through all the patterns until one matches or there is an error other+ than NOMATCH. This code is in a subroutine so that it can be re-used for+ finding subsequent matches when colouring matched lines. After finding one+ match, set PCRE2_NOTEMPTY to disable any further matches of null strings in+ this line. */++ match = match_patterns(ptr, length, options, startoffset, &mrc);+ options = PCRE2_NOTEMPTY;++ /* If it's a match or a not-match (as required), do what's wanted. NOTE: Use+ only FWRITE_IGNORE() - which is just a packaged fwrite() that ignores its+ return code - to output data lines, so that binary zeroes are treated as just+ another data character. */++ if (match != invert)+ {+ BOOL hyphenprinted = FALSE;++ /* We've failed if we want a file that doesn't have any matches. */++ if (filenames == FN_NOMATCH_ONLY) return 1;++ /* Remember that this line matched (for counting matched lines) */++ line_matched = TRUE;++ /* If all we want is a yes/no answer, we can return immediately. */++ if (quiet) return 0;++ /* Just count if just counting is wanted. */++ else if (count_only || show_total_count) count++;++ /* When handling a binary file and binary-files==binary, the "binary"+ variable will be set true (it's false in all other cases). In this+ situation we just want to output the file name. No need to scan further. */++ else if (binary)+ {+ fprintf(stdout, "Binary file %s matches" STDOUT_NL, filename);+ return 0;+ }++ /* Likewise, if all we want is a file name, there is no need to scan any+ more lines in the file. */++ else if (filenames == FN_MATCH_ONLY)+ {+ fprintf(stdout, "%s" STDOUT_NL, printname);+ return 0;+ }++ /* The --only-matching option prints just the substring that matched,+ and/or one or more captured portions of it, as long as these strings are+ not empty. The --file-offsets and --line-offsets options output offsets for+ the matching substring (all three set only_matching_count non-zero). None+ of these mutually exclusive options prints any context. Afterwards, adjust+ the start and then jump back to look for further matches in the same line.+ If we are in invert mode, however, nothing is printed and we do not restart+ - this could still be useful because the return code is set. */++ else if (only_matching_count != 0)+ {+ if (!invert)+ {+ PCRE2_SIZE oldstartoffset;++ if (printname != NULL) fprintf(stdout, "%s:", printname);+ if (number) fprintf(stdout, "%lu:", linenumber);++ /* Handle --line-offsets */++ if (line_offsets)+ fprintf(stdout, "%d,%d" STDOUT_NL, (int)(ptr + offsets[0] - ptr),+ (int)(offsets[1] - offsets[0]));++ /* Handle --file-offsets */++ else if (file_offsets)+ fprintf(stdout, "%d,%d" STDOUT_NL,+ (int)(filepos + ptr + offsets[0] - ptr),+ (int)(offsets[1] - offsets[0]));++ /* Handle --output (which has already been syntax checked) */++ else if (output_text != NULL)+ {+ if (display_output_text((PCRE2_SPTR)output_text, FALSE,+ (PCRE2_SPTR)ptr, offsets, mrc) || printname != NULL ||+ number)+ fprintf(stdout, STDOUT_NL);+ }++ /* Handle --only-matching, which may occur many times */++ else+ {+ BOOL printed = FALSE;+ omstr *om;++ for (om = only_matching; om != NULL; om = om->next)+ {+ int n = om->groupnum;+ if (n == 0 || n < mrc)+ {+ int plen = offsets[2*n + 1] - offsets[2*n];+ if (plen > 0)+ {+ if (printed && om_separator != NULL)+ fprintf(stdout, "%s", om_separator);+ print_match(ptr + offsets[n*2], plen);+ printed = TRUE;+ }+ }+ }++ if (printed || printname != NULL || number)+ fprintf(stdout, STDOUT_NL);+ }++ /* Prepare to repeat to find the next match in the line. */++ match = FALSE;+ if (line_buffered) fflush(stdout);+ rc = 0; /* Had some success */++ /* If the pattern contained a lookbehind that included \K, it is+ possible that the end of the match might be at or before the actual+ starting offset we have just used. In this case, start one character+ further on. */++ startoffset = offsets[1]; /* Restart after the match */+ oldstartoffset = pcre2_get_startchar(match_data);+ if (startoffset <= oldstartoffset)+ {+ if (startoffset >= length) goto END_ONE_MATCH; /* Were at end */+ startoffset = oldstartoffset + 1;+ if (utf) while ((ptr[startoffset] & 0xc0) == 0x80) startoffset++;+ }++ /* If the current match ended past the end of the line (only possible+ in multiline mode), we must move on to the line in which it did end+ before searching for more matches. */++ while (startoffset > linelength)+ {+ ptr += linelength + endlinelength;+ filepos += (int)(linelength + endlinelength);+ linenumber++;+ startoffset -= (int)(linelength + endlinelength);+ t = end_of_line(ptr, endptr, &endlinelength);+ linelength = t - ptr - endlinelength;+ length = (PCRE2_SIZE)(endptr - ptr);+ }++ goto ONLY_MATCHING_RESTART;+ }+ }++ /* This is the default case when none of the above options is set. We print+ the matching lines(s), possibly preceded and/or followed by other lines of+ context. */++ else+ {+ lines_printed = TRUE;++ /* See if there is a requirement to print some "after" lines from a+ previous match. We never print any overlaps. */++ if (after_context > 0 && lastmatchnumber > 0)+ {+ int ellength;+ int linecount = 0;+ char *p = lastmatchrestart;++ while (p < ptr && linecount < after_context)+ {+ p = end_of_line(p, ptr, &ellength);+ linecount++;+ }++ /* It is important to advance lastmatchrestart during this printing so+ that it interacts correctly with any "before" printing below. Print+ each line's data using fwrite() in case there are binary zeroes. */++ while (lastmatchrestart < p)+ {+ char *pp = lastmatchrestart;+ if (printname != NULL) fprintf(stdout, "%s-", printname);+ if (number) fprintf(stdout, "%lu-", lastmatchnumber++);+ pp = end_of_line(pp, endptr, &ellength);+ FWRITE_IGNORE(lastmatchrestart, 1, pp - lastmatchrestart, stdout);+ lastmatchrestart = pp;+ }+ if (lastmatchrestart != ptr) hyphenpending = TRUE;+ }++ /* If there were non-contiguous lines printed above, insert hyphens. */++ if (hyphenpending)+ {+ fprintf(stdout, "--" STDOUT_NL);+ hyphenpending = FALSE;+ hyphenprinted = TRUE;+ }++ /* See if there is a requirement to print some "before" lines for this+ match. Again, don't print overlaps. */++ if (before_context > 0)+ {+ int linecount = 0;+ char *p = ptr;++ while (p > main_buffer &&+ (lastmatchnumber == 0 || p > lastmatchrestart) &&+ linecount < before_context)+ {+ linecount++;+ p = previous_line(p, main_buffer);+ }++ if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)+ fprintf(stdout, "--" STDOUT_NL);++ while (p < ptr)+ {+ int ellength;+ char *pp = p;+ if (printname != NULL) fprintf(stdout, "%s-", printname);+ if (number) fprintf(stdout, "%lu-", linenumber - linecount--);+ pp = end_of_line(pp, endptr, &ellength);+ FWRITE_IGNORE(p, 1, pp - p, stdout);+ p = pp;+ }+ }++ /* Now print the matching line(s); ensure we set hyphenpending at the end+ of the file if any context lines are being output. */++ if (after_context > 0 || before_context > 0)+ endhyphenpending = TRUE;++ if (printname != NULL) fprintf(stdout, "%s:", printname);+ if (number) fprintf(stdout, "%lu:", linenumber);++ /* This extra option, for Jeffrey Friedl's debugging requirements,+ replaces the matched string, or a specific captured string if it exists,+ with X. When this happens, colouring is ignored. */++#ifdef JFRIEDL_DEBUG+ if (S_arg >= 0 && S_arg < mrc)+ {+ int first = S_arg * 2;+ int last = first + 1;+ FWRITE_IGNORE(ptr, 1, offsets[first], stdout);+ fprintf(stdout, "X");+ FWRITE_IGNORE(ptr + offsets[last], 1, linelength - offsets[last], stdout);+ }+ else+#endif++ /* In multiline mode, or if colouring, we have to split the line(s) up+ and search for further matches, but not of course if the line is a+ non-match. In multiline mode this is necessary in case there is another+ match that spans the end of the current line. When colouring we want to+ colour all matches. */++ if ((multiline || do_colour) && !invert)+ {+ int plength;+ PCRE2_SIZE endprevious;++ /* The use of \K may make the end offset earlier than the start. In+ this situation, swap them round. */++ if (offsets[0] > offsets[1])+ {+ PCRE2_SIZE temp = offsets[0];+ offsets[0] = offsets[1];+ offsets[1] = temp;+ }++ FWRITE_IGNORE(ptr, 1, offsets[0], stdout);+ print_match(ptr + offsets[0], offsets[1] - offsets[0]);++ for (;;)+ {+ PCRE2_SIZE oldstartoffset = pcre2_get_startchar(match_data);++ endprevious = offsets[1];+ startoffset = endprevious; /* Advance after previous match. */++ /* If the pattern contained a lookbehind that included \K, it is+ possible that the end of the match might be at or before the actual+ starting offset we have just used. In this case, start one character+ further on. */++ if (startoffset <= oldstartoffset)+ {+ startoffset = oldstartoffset + 1;+ if (utf) while ((ptr[startoffset] & 0xc0) == 0x80) startoffset++;+ }++ /* If the current match ended past the end of the line (only possible+ in multiline mode), we must move on to the line in which it did end+ before searching for more matches. Because the PCRE2_FIRSTLINE option+ is set, the start of the match will always be before the first+ newline sequence. */++ while (startoffset > linelength + endlinelength)+ {+ ptr += linelength + endlinelength;+ filepos += (int)(linelength + endlinelength);+ linenumber++;+ startoffset -= (int)(linelength + endlinelength);+ endprevious -= (int)(linelength + endlinelength);+ t = end_of_line(ptr, endptr, &endlinelength);+ linelength = t - ptr - endlinelength;+ length = (PCRE2_SIZE)(endptr - ptr);+ }++ /* If startoffset is at the exact end of the line it means this+ complete line was the final part of the match, so there is nothing+ more to do. */++ if (startoffset == linelength + endlinelength) break;++ /* Otherwise, run a match from within the final line, and if found,+ loop for any that may follow. */++ if (!match_patterns(ptr, length, options, startoffset, &mrc)) break;++ /* The use of \K may make the end offset earlier than the start. In+ this situation, swap them round. */++ if (offsets[0] > offsets[1])+ {+ PCRE2_SIZE temp = offsets[0];+ offsets[0] = offsets[1];+ offsets[1] = temp;+ }++ FWRITE_IGNORE(ptr + endprevious, 1, offsets[0] - endprevious, stdout);+ print_match(ptr + offsets[0], offsets[1] - offsets[0]);+ }++ /* In multiline mode, we may have already printed the complete line+ and its line-ending characters (if they matched the pattern), so there+ may be no more to print. */++ plength = (int)((linelength + endlinelength) - endprevious);+ if (plength > 0) FWRITE_IGNORE(ptr + endprevious, 1, plength, stdout);+ }++ /* Not colouring or multiline; no need to search for further matches. */++ else FWRITE_IGNORE(ptr, 1, linelength + endlinelength, stdout);+ }++ /* End of doing what has to be done for a match. If --line-buffered was+ given, flush the output. */++ if (line_buffered) fflush(stdout);+ rc = 0; /* Had some success */++ /* Remember where the last match happened for after_context. We remember+ where we are about to restart, and that line's number. */++ lastmatchrestart = ptr + linelength + endlinelength;+ lastmatchnumber = linenumber + 1;++ /* If a line was printed and we are now at the end of the file and the last+ line had no newline, output one. */++ if (lines_printed && lastmatchrestart >= endptr && endlinelength == 0)+ write_final_newline();+ }++ /* For a match in multiline inverted mode (which of course did not cause+ anything to be printed), we have to move on to the end of the match before+ proceeding. */++ if (multiline && invert && match)+ {+ int ellength;+ char *endmatch = ptr + offsets[1];+ t = ptr;+ while (t < endmatch)+ {+ t = end_of_line(t, endptr, &ellength);+ if (t <= endmatch) linenumber++; else break;+ }+ endmatch = end_of_line(endmatch, endptr, &ellength);+ linelength = endmatch - ptr - ellength;+ }++ /* Advance to after the newline and increment the line number. The file+ offset to the current line is maintained in filepos. */++ END_ONE_MATCH:+ ptr += linelength + endlinelength;+ filepos += (int)(linelength + endlinelength);+ linenumber++;++ /* If there was at least one match (or a non-match, as required) in the line,+ increment the count for the -m option. */++ if (line_matched) count_matched_lines++;++ /* If input is line buffered, and the buffer is not yet full, read another+ line and add it into the buffer. */++ if (input_line_buffered && bufflength < (PCRE2_SIZE)bufsize)+ {+ int add = read_one_line(ptr, bufsize - (int)(ptr - main_buffer), in);+ bufflength += add;+ endptr += add;+ }++ /* If we haven't yet reached the end of the file (the buffer is full), and+ the current point is in the top 1/3 of the buffer, slide the buffer down by+ 1/3 and refill it. Before we do this, if some unprinted "after" lines are+ about to be lost, print them. */++ if (bufflength >= (PCRE2_SIZE)bufsize && ptr > main_buffer + 2*bufthird)+ {+ if (after_context > 0 &&+ lastmatchnumber > 0 &&+ lastmatchrestart < main_buffer + bufthird)+ {+ do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);+ lastmatchnumber = 0; /* Indicates no after lines pending */+ }++ /* Now do the shuffle */++ (void)memmove(main_buffer, main_buffer + bufthird, 2*bufthird);+ ptr -= bufthird;++ bufflength = 2*bufthird + fill_buffer(handle, frtype,+ main_buffer + 2*bufthird, bufthird, input_line_buffered);+ endptr = main_buffer + bufflength;++ /* Adjust any last match point */++ if (lastmatchnumber > 0) lastmatchrestart -= bufthird;+ }+ } /* Loop through the whole file */++/* End of file; print final "after" lines if wanted; do_after_lines sets+hyphenpending if it prints something. */++if (only_matching_count == 0 && !(count_only|show_total_count))+ {+ do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);+ hyphenpending |= endhyphenpending;+ }++/* Print the file name if we are looking for those without matches and there+were none. If we found a match, we won't have got this far. */++if (filenames == FN_NOMATCH_ONLY)+ {+ fprintf(stdout, "%s" STDOUT_NL, printname);+ return 0;+ }++/* Print the match count if wanted */++if (count_only && !quiet)+ {+ if (count > 0 || !omit_zero_count)+ {+ if (printname != NULL && filenames != FN_NONE)+ fprintf(stdout, "%s:", printname);+ fprintf(stdout, "%lu" STDOUT_NL, count);+ counts_printed++;+ }+ }++total_count += count; /* Can be set without count_only */+return rc;+}++++/*************************************************+* Grep a file or recurse into a directory *+*************************************************/++/* Given a path name, if it's a directory, scan all the files if we are+recursing; if it's a file, grep it.++Arguments:+ pathname the path to investigate+ dir_recurse TRUE if recursing is wanted (-r or -drecurse)+ only_one_at_top TRUE if the path is the only one at toplevel++Returns: -1 the file/directory was skipped+ 0 if there was at least one match+ 1 if there were no matches+ 2 there was some kind of error++However, file opening failures are suppressed if "silent" is set.+*/++static int+grep_or_recurse(char *pathname, BOOL dir_recurse, BOOL only_one_at_top)+{+int rc = 1;+int frtype;+void *handle;+char *lastcomp;+FILE *in = NULL; /* Ensure initialized */++#ifdef SUPPORT_LIBZ+gzFile ingz = NULL;+#endif++#ifdef SUPPORT_LIBBZ2+BZFILE *inbz2 = NULL;+#endif++#if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2+int pathlen;+#endif++#if defined NATIVE_ZOS+int zos_type;+FILE *zos_test_file;+#endif++/* If the file name is "-" we scan stdin */++if (strcmp(pathname, "-") == 0)+ {+ return pcre2grep(stdin, FR_PLAIN, stdin_name,+ (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))?+ stdin_name : NULL);+ }++/* Inclusion and exclusion: --include-dir and --exclude-dir apply only to+directories, whereas --include and --exclude apply to everything else. The test+is against the final component of the path. */++lastcomp = strrchr(pathname, FILESEP);+lastcomp = (lastcomp == NULL)? pathname : lastcomp + 1;++/* If the file is a directory, skip if not recursing or if explicitly excluded.+Otherwise, scan the directory and recurse for each path within it. The scanning+code is localized so it can be made system-specific. */+++/* For z/OS, determine the file type. */++#if defined NATIVE_ZOS+zos_test_file = fopen(pathname,"rb");++if (zos_test_file == NULL)+ {+ if (!silent) fprintf(stderr, "pcre2grep: failed to test next file %s\n",+ pathname, strerror(errno));+ return -1;+ }+zos_type = identifyzosfiletype (zos_test_file);+fclose (zos_test_file);++/* Handle a PDS in separate code */++if (zos_type == __ZOS_PDS || zos_type == __ZOS_PDSE)+ {+ return travelonpdsdir (pathname, only_one_at_top);+ }++/* Deal with regular files in the normal way below. These types are:+ zos_type == __ZOS_PDS_MEMBER+ zos_type == __ZOS_PS+ zos_type == __ZOS_VSAM_KSDS+ zos_type == __ZOS_VSAM_ESDS+ zos_type == __ZOS_VSAM_RRDS+*/++/* Handle a z/OS directory using common code. */++else if (zos_type == __ZOS_HFS)+ {+#endif /* NATIVE_ZOS */+++/* Handle directories: common code for all OS */++if (isdirectory(pathname))+ {+ if (dee_action == dee_SKIP ||+ !test_incexc(lastcomp, include_dir_patterns, exclude_dir_patterns))+ return -1;++ if (dee_action == dee_RECURSE)+ {+ char buffer[FNBUFSIZ];+ char *nextfile;+ directory_type *dir = opendirectory(pathname);++ if (dir == NULL)+ {+ if (!silent)+ fprintf(stderr, "pcre2grep: Failed to open directory %s: %s\n", pathname,+ strerror(errno));+ return 2;+ }++ while ((nextfile = readdirectory(dir)) != NULL)+ {+ int frc;+ int fnlength = strlen(pathname) + strlen(nextfile) + 2;+ if (fnlength > FNBUFSIZ)+ {+ fprintf(stderr, "pcre2grep: recursive filename is too long\n");+ rc = 2;+ break;+ }+ sprintf(buffer, "%s%c%s", pathname, FILESEP, nextfile);+ frc = grep_or_recurse(buffer, dir_recurse, FALSE);+ if (frc > 1) rc = frc;+ else if (frc == 0 && rc == 1) rc = 0;+ }++ closedirectory(dir);+ return rc;+ }+ }++#ifdef WIN32+if (iswild(pathname))+ {+ char buffer[1024];+ char *nextfile;+ char *name;+ directory_type *dir = opendirectory(pathname);++ if (dir == NULL)+ return 0;++ for (nextfile = name = pathname; *nextfile != 0; nextfile++)+ if (*nextfile == '/' || *nextfile == '\\')+ name = nextfile + 1;+ *name = 0;++ while ((nextfile = readdirectory(dir)) != NULL)+ {+ int frc;+ sprintf(buffer, "%.512s%.128s", pathname, nextfile);+ frc = grep_or_recurse(buffer, dir_recurse, FALSE);+ if (frc > 1) rc = frc;+ else if (frc == 0 && rc == 1) rc = 0;+ }++ closedirectory(dir);+ return rc;+ }+#endif++#if defined NATIVE_ZOS+ }+#endif++/* If the file is not a directory, check for a regular file, and if it is not,+skip it if that's been requested. Otherwise, check for an explicit inclusion or+exclusion. */++else if (+#if defined NATIVE_ZOS+ (zos_type == __ZOS_NOFILE && DEE_action == DEE_SKIP) ||+#else /* all other OS */+ (!isregfile(pathname) && DEE_action == DEE_SKIP) ||+#endif+ !test_incexc(lastcomp, include_patterns, exclude_patterns))+ return -1; /* File skipped */++/* Control reaches here if we have a regular file, or if we have a directory+and recursion or skipping was not requested, or if we have anything else and+skipping was not requested. The scan proceeds. If this is the first and only+argument at top level, we don't show the file name, unless we are only showing+the file name, or the filename was forced (-H). */++#if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2+pathlen = (int)(strlen(pathname));+#endif++/* Open using zlib if it is supported and the file name ends with .gz. */++#ifdef SUPPORT_LIBZ+if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0)+ {+ ingz = gzopen(pathname, "rb");+ if (ingz == NULL)+ {+ if (!silent)+ fprintf(stderr, "pcre2grep: Failed to open %s: %s\n", pathname,+ strerror(errno));+ return 2;+ }+ handle = (void *)ingz;+ frtype = FR_LIBZ;+ }+else+#endif++/* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */++#ifdef SUPPORT_LIBBZ2+if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0)+ {+ inbz2 = BZ2_bzopen(pathname, "rb");+ handle = (void *)inbz2;+ frtype = FR_LIBBZ2;+ }+else+#endif++/* Otherwise use plain fopen(). The label is so that we can come back here if+an attempt to read a .bz2 file indicates that it really is a plain file. */++#ifdef SUPPORT_LIBBZ2+PLAIN_FILE:+#endif+ {+ in = fopen(pathname, "rb");+ handle = (void *)in;+ frtype = FR_PLAIN;+ }++/* All the opening methods return errno when they fail. */++if (handle == NULL)+ {+ if (!silent)+ fprintf(stderr, "pcre2grep: Failed to open %s: %s\n", pathname,+ strerror(errno));+ return 2;+ }++/* Now grep the file */++rc = pcre2grep(handle, frtype, pathname, (filenames > FN_DEFAULT ||+ (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);++/* Close in an appropriate manner. */++#ifdef SUPPORT_LIBZ+if (frtype == FR_LIBZ)+ gzclose(ingz);+else+#endif++/* If it is a .bz2 file and the result is 3, it means that the first attempt to+read failed. If the error indicates that the file isn't in fact bzipped, try+again as a normal file. */++#ifdef SUPPORT_LIBBZ2+if (frtype == FR_LIBBZ2)+ {+ if (rc == 3)+ {+ int errnum;+ const char *err = BZ2_bzerror(inbz2, &errnum);+ if (errnum == BZ_DATA_ERROR_MAGIC)+ {+ BZ2_bzclose(inbz2);+ goto PLAIN_FILE;+ }+ else if (!silent)+ fprintf(stderr, "pcre2grep: Failed to read %s using bzlib: %s\n",+ pathname, err);+ rc = 2; /* The normal "something went wrong" code */+ }+ BZ2_bzclose(inbz2);+ }+else+#endif++/* Normal file close */++fclose(in);++/* Pass back the yield from pcre2grep(). */++return rc;+}++++/*************************************************+* Handle a single-letter, no data option *+*************************************************/++static int+handle_option(int letter, int options)+{+switch(letter)+ {+ case N_FOFFSETS: file_offsets = TRUE; break;+ case N_HELP: help(); pcre2grep_exit(0); break; /* Stops compiler warning */+ case N_LBUFFER: line_buffered = TRUE; break;+ case N_LOFFSETS: line_offsets = number = TRUE; break;+ case N_NOJIT: use_jit = FALSE; break;+ case 'a': binary_files = BIN_TEXT; break;+ case 'c': count_only = TRUE; break;+ case 'F': options |= PCRE2_LITERAL; break;+ case 'H': filenames = FN_FORCE; break;+ case 'I': binary_files = BIN_NOMATCH; break;+ case 'h': filenames = FN_NONE; break;+ case 'i': options |= PCRE2_CASELESS; break;+ case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break;+ case 'L': filenames = FN_NOMATCH_ONLY; break;+ case 'M': multiline = TRUE; options |= PCRE2_MULTILINE|PCRE2_FIRSTLINE; break;+ case 'n': number = TRUE; break;++ case 'o':+ only_matching_last = add_number(0, only_matching_last);+ if (only_matching == NULL) only_matching = only_matching_last;+ break;++ case 'q': quiet = TRUE; break;+ case 'r': dee_action = dee_RECURSE; break;+ case 's': silent = TRUE; break;+ case 't': show_total_count = TRUE; break;+ case 'u': options |= PCRE2_UTF; utf = TRUE; break;+ case 'U': options |= PCRE2_UTF|PCRE2_MATCH_INVALID_UTF; utf = TRUE; break;+ case 'v': invert = TRUE; break;+ case 'w': extra_options |= PCRE2_EXTRA_MATCH_WORD; break;+ case 'x': extra_options |= PCRE2_EXTRA_MATCH_LINE; break;++ case 'V':+ {+ unsigned char buffer[128];+ (void)pcre2_config(PCRE2_CONFIG_VERSION, buffer);+ fprintf(stdout, "pcre2grep version %s" STDOUT_NL, buffer);+ }+ pcre2grep_exit(0);+ break;++ default:+ fprintf(stderr, "pcre2grep: Unknown option -%c\n", letter);+ pcre2grep_exit(usage(2));+ }++return options;+}++++/*************************************************+* Construct printed ordinal *+*************************************************/++/* This turns a number into "1st", "3rd", etc. */++static char *+ordin(int n)+{+static char buffer[14];+char *p = buffer;+sprintf(p, "%d", n);+while (*p != 0) p++;+n %= 100;+if (n >= 11 && n <= 13) n = 0;+switch (n%10)+ {+ case 1: strcpy(p, "st"); break;+ case 2: strcpy(p, "nd"); break;+ case 3: strcpy(p, "rd"); break;+ default: strcpy(p, "th"); break;+ }+return buffer;+}++++/*************************************************+* Compile a single pattern *+*************************************************/++/* Do nothing if the pattern has already been compiled. This is the case for+include/exclude patterns read from a file.++When the -F option has been used, each "pattern" may be a list of strings,+separated by line breaks. They will be matched literally. We split such a+string and compile the first substring, inserting an additional block into the+pattern chain.++Arguments:+ p points to the pattern block+ options the PCRE options+ fromfile TRUE if the pattern was read from a file+ fromtext file name or identifying text (e.g. "include")+ count 0 if this is the only command line pattern, or+ number of the command line pattern, or+ linenumber for a pattern from a file++Returns: TRUE on success, FALSE after an error+*/++static BOOL+compile_pattern(patstr *p, int options, int fromfile, const char *fromtext,+ int count)+{+char *ps;+int errcode;+PCRE2_SIZE patlen, erroffset;+PCRE2_UCHAR errmessbuffer[ERRBUFSIZ];++if (p->compiled != NULL) return TRUE;+ps = p->string;+patlen = p->length;++if ((options & PCRE2_LITERAL) != 0)+ {+ int ellength;+ char *eop = ps + patlen;+ char *pe = end_of_line(ps, eop, &ellength);++ if (ellength != 0)+ {+ patlen = pe - ps - ellength;+ if (add_pattern(pe, p->length-patlen-ellength, p) == NULL) return FALSE;+ }+ }++p->compiled = pcre2_compile((PCRE2_SPTR)ps, patlen, options, &errcode,+ &erroffset, compile_context);++/* Handle successful compile. Try JIT-compiling if supported and enabled. We+ignore any JIT compiler errors, relying falling back to interpreting if+anything goes wrong with JIT. */++if (p->compiled != NULL)+ {+#ifdef SUPPORT_PCRE2GREP_JIT+ if (use_jit) (void)pcre2_jit_compile(p->compiled, PCRE2_JIT_COMPLETE);+#endif+ return TRUE;+ }++/* Handle compile errors */++if (erroffset > patlen) erroffset = patlen;+pcre2_get_error_message(errcode, errmessbuffer, sizeof(errmessbuffer));++if (fromfile)+ {+ fprintf(stderr, "pcre2grep: Error in regex in line %d of %s "+ "at offset %d: %s\n", count, fromtext, (int)erroffset, errmessbuffer);+ }+else+ {+ if (count == 0)+ fprintf(stderr, "pcre2grep: Error in %s regex at offset %d: %s\n",+ fromtext, (int)erroffset, errmessbuffer);+ else+ fprintf(stderr, "pcre2grep: Error in %s %s regex at offset %d: %s\n",+ ordin(count), fromtext, (int)erroffset, errmessbuffer);+ }++return FALSE;+}++++/*************************************************+* Read and compile a file of patterns *+*************************************************/++/* This is used for --filelist, --include-from, and --exclude-from.++Arguments:+ name the name of the file; "-" is stdin+ patptr pointer to the pattern chain anchor+ patlastptr pointer to the last pattern pointer++Returns: TRUE if all went well+*/++static BOOL+read_pattern_file(char *name, patstr **patptr, patstr **patlastptr)+{+int linenumber = 0;+PCRE2_SIZE patlen;+FILE *f;+const char *filename;+char buffer[MAXPATLEN+20];++if (strcmp(name, "-") == 0)+ {+ f = stdin;+ filename = stdin_name;+ }+else+ {+ f = fopen(name, "r");+ if (f == NULL)+ {+ fprintf(stderr, "pcre2grep: Failed to open %s: %s\n", name, strerror(errno));+ return FALSE;+ }+ filename = name;+ }++while ((patlen = read_one_line(buffer, sizeof(buffer), f)) > 0)+ {+ while (patlen > 0 && isspace((unsigned char)(buffer[patlen-1]))) patlen--;+ linenumber++;+ if (patlen == 0) continue; /* Skip blank lines */++ /* Note: this call to add_pattern() puts a pointer to the local variable+ "buffer" into the pattern chain. However, that pointer is used only when+ compiling the pattern, which happens immediately below, so we flatten it+ afterwards, as a precaution against any later code trying to use it. */++ *patlastptr = add_pattern(buffer, patlen, *patlastptr);+ if (*patlastptr == NULL)+ {+ if (f != stdin) fclose(f);+ return FALSE;+ }+ if (*patptr == NULL) *patptr = *patlastptr;++ /* This loop is needed because compiling a "pattern" when -F is set may add+ on additional literal patterns if the original contains a newline. In the+ common case, it never will, because read_one_line() stops at a newline.+ However, the -N option can be used to give pcre2grep a different newline+ setting. */++ for(;;)+ {+ if (!compile_pattern(*patlastptr, pcre2_options, TRUE, filename,+ linenumber))+ {+ if (f != stdin) fclose(f);+ return FALSE;+ }+ (*patlastptr)->string = NULL; /* Insurance */+ if ((*patlastptr)->next == NULL) break;+ *patlastptr = (*patlastptr)->next;+ }+ }++if (f != stdin) fclose(f);+return TRUE;+}++++/*************************************************+* Main program *+*************************************************/++/* Returns 0 if something matched, 1 if nothing matched, 2 after an error. */++int+main(int argc, char **argv)+{+int i, j;+int rc = 1;+BOOL only_one_at_top;+patstr *cp;+fnstr *fn;+omstr *om;+const char *locale_from = "--locale";++#ifdef SUPPORT_PCRE2GREP_JIT+pcre2_jit_stack *jit_stack = NULL;+#endif++/* In Windows, stdout is set up as a text stream, which means that \n is+converted to \r\n. This causes output lines that are copied from the input to+change from ....\r\n to ....\r\r\n, which is not right. We therefore ensure+that stdout is a binary stream. Note that this means all other output to stdout+must use STDOUT_NL to terminate lines. */++#ifdef WIN32+_setmode(_fileno(stdout), _O_BINARY);+#endif++/* Process the options */++for (i = 1; i < argc; i++)+ {+ option_item *op = NULL;+ char *option_data = (char *)""; /* default to keep compiler happy */+ BOOL longop;+ BOOL longopwasequals = FALSE;++ if (argv[i][0] != '-') break;++ /* If we hit an argument that is just "-", it may be a reference to STDIN,+ but only if we have previously had -e or -f to define the patterns. */++ if (argv[i][1] == 0)+ {+ if (pattern_files != NULL || patterns != NULL) break;+ else pcre2grep_exit(usage(2));+ }++ /* Handle a long name option, or -- to terminate the options */++ if (argv[i][1] == '-')+ {+ char *arg = argv[i] + 2;+ char *argequals = strchr(arg, '=');++ if (*arg == 0) /* -- terminates options */+ {+ i++;+ break; /* out of the options-handling loop */+ }++ longop = TRUE;++ /* Some long options have data that follows after =, for example file=name.+ Some options have variations in the long name spelling: specifically, we+ allow "regexp" because GNU grep allows it, though I personally go along+ with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p".+ These options are entered in the table as "regex(p)". Options can be in+ both these categories. */++ for (op = optionlist; op->one_char != 0; op++)+ {+ char *opbra = strchr(op->long_name, '(');+ char *equals = strchr(op->long_name, '=');++ /* Handle options with only one spelling of the name */++ if (opbra == NULL) /* Does not contain '(' */+ {+ if (equals == NULL) /* Not thing=data case */+ {+ if (strcmp(arg, op->long_name) == 0) break;+ }+ else /* Special case xxx=data */+ {+ int oplen = (int)(equals - op->long_name);+ int arglen = (argequals == NULL)?+ (int)strlen(arg) : (int)(argequals - arg);+ if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0)+ {+ option_data = arg + arglen;+ if (*option_data == '=')+ {+ option_data++;+ longopwasequals = TRUE;+ }+ break;+ }+ }+ }++ /* Handle options with an alternate spelling of the name */++ else+ {+ char buff1[24];+ char buff2[24];+ int ret;++ int baselen = (int)(opbra - op->long_name);+ int fulllen = (int)(strchr(op->long_name, ')') - op->long_name + 1);+ int arglen = (argequals == NULL || equals == NULL)?+ (int)strlen(arg) : (int)(argequals - arg);++ if ((ret = snprintf(buff1, sizeof(buff1), "%.*s", baselen, op->long_name),+ ret < 0 || ret > (int)sizeof(buff1)) ||+ (ret = snprintf(buff2, sizeof(buff2), "%s%.*s", buff1,+ fulllen - baselen - 2, opbra + 1),+ ret < 0 || ret > (int)sizeof(buff2)))+ {+ fprintf(stderr, "pcre2grep: Buffer overflow when parsing %s option\n",+ op->long_name);+ pcre2grep_exit(2);+ }++ if (strncmp(arg, buff1, arglen) == 0 ||+ strncmp(arg, buff2, arglen) == 0)+ {+ if (equals != NULL && argequals != NULL)+ {+ option_data = argequals;+ if (*option_data == '=')+ {+ option_data++;+ longopwasequals = TRUE;+ }+ }+ break;+ }+ }+ }++ if (op->one_char == 0)+ {+ fprintf(stderr, "pcre2grep: Unknown option %s\n", argv[i]);+ pcre2grep_exit(usage(2));+ }+ }++ /* Jeffrey Friedl's debugging harness uses these additional options which+ are not in the right form for putting in the option table because they use+ only one hyphen, yet are more than one character long. By putting them+ separately here, they will not get displayed as part of the help() output,+ but I don't think Jeffrey will care about that. */++#ifdef JFRIEDL_DEBUG+ else if (strcmp(argv[i], "-pre") == 0) {+ jfriedl_prefix = argv[++i];+ continue;+ } else if (strcmp(argv[i], "-post") == 0) {+ jfriedl_postfix = argv[++i];+ continue;+ } else if (strcmp(argv[i], "-XT") == 0) {+ sscanf(argv[++i], "%d", &jfriedl_XT);+ continue;+ } else if (strcmp(argv[i], "-XR") == 0) {+ sscanf(argv[++i], "%d", &jfriedl_XR);+ continue;+ }+#endif+++ /* One-char options; many that have no data may be in a single argument; we+ continue till we hit the last one or one that needs data. */++ else+ {+ char *s = argv[i] + 1;+ longop = FALSE;++ while (*s != 0)+ {+ for (op = optionlist; op->one_char != 0; op++)+ {+ if (*s == op->one_char) break;+ }+ if (op->one_char == 0)+ {+ fprintf(stderr, "pcre2grep: Unknown option letter '%c' in \"%s\"\n",+ *s, argv[i]);+ pcre2grep_exit(usage(2));+ }++ option_data = s+1;++ /* Break out if this is the last character in the string; it's handled+ below like a single multi-char option. */++ if (*option_data == 0) break;++ /* Check for a single-character option that has data: OP_OP_NUMBER(S)+ are used for ones that either have a numerical number or defaults, i.e.+ the data is optional. If a digit follows, there is data; if not, carry on+ with other single-character options in the same string. */++ if (op->type == OP_OP_NUMBER || op->type == OP_OP_NUMBERS)+ {+ if (isdigit((unsigned char)s[1])) break;+ }+ else /* Check for an option with data */+ {+ if (op->type != OP_NODATA) break;+ }++ /* Handle a single-character option with no data, then loop for the+ next character in the string. */++ pcre2_options = handle_option(*s++, pcre2_options);+ }+ }++ /* At this point we should have op pointing to a matched option. If the type+ is NO_DATA, it means that there is no data, and the option might set+ something in the PCRE options. */++ if (op->type == OP_NODATA)+ {+ pcre2_options = handle_option(op->one_char, pcre2_options);+ continue;+ }++ /* If the option type is OP_OP_STRING or OP_OP_NUMBER(S), it's an option that+ either has a value or defaults to something. It cannot have data in a+ separate item. At the moment, the only such options are "colo(u)r",+ "only-matching", and Jeffrey Friedl's special -S debugging option. */++ if (*option_data == 0 &&+ (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER ||+ op->type == OP_OP_NUMBERS))+ {+ switch (op->one_char)+ {+ case N_COLOUR:+ colour_option = "auto";+ break;++ case 'o':+ only_matching_last = add_number(0, only_matching_last);+ if (only_matching == NULL) only_matching = only_matching_last;+ break;++#ifdef JFRIEDL_DEBUG+ case 'S':+ S_arg = 0;+ break;+#endif+ }+ continue;+ }++ /* Otherwise, find the data string for the option. */++ if (*option_data == 0)+ {+ if (i >= argc - 1 || longopwasequals)+ {+ fprintf(stderr, "pcre2grep: Data missing after %s\n", argv[i]);+ pcre2grep_exit(usage(2));+ }+ option_data = argv[++i];+ }++ /* If the option type is OP_OP_NUMBERS, the value is a number that is to be+ added to a chain of numbers. */++ if (op->type == OP_OP_NUMBERS)+ {+ unsigned long int n = decode_number(option_data, op, longop);+ omdatastr *omd = (omdatastr *)op->dataptr;+ *(omd->lastptr) = add_number((int)n, *(omd->lastptr));+ if (*(omd->anchor) == NULL) *(omd->anchor) = *(omd->lastptr);+ }++ /* If the option type is OP_PATLIST, it's the -e option, or one of the+ include/exclude options, which can be called multiple times to create lists+ of patterns. */++ else if (op->type == OP_PATLIST)+ {+ patdatastr *pd = (patdatastr *)op->dataptr;+ *(pd->lastptr) = add_pattern(option_data, (PCRE2_SIZE)strlen(option_data),+ *(pd->lastptr));+ if (*(pd->lastptr) == NULL) goto EXIT2;+ if (*(pd->anchor) == NULL) *(pd->anchor) = *(pd->lastptr);+ }++ /* If the option type is OP_FILELIST, it's one of the options that names a+ file. */++ else if (op->type == OP_FILELIST)+ {+ fndatastr *fd = (fndatastr *)op->dataptr;+ fn = (fnstr *)malloc(sizeof(fnstr));+ if (fn == NULL)+ {+ fprintf(stderr, "pcre2grep: malloc failed\n");+ goto EXIT2;+ }+ fn->next = NULL;+ fn->name = option_data;+ if (*(fd->anchor) == NULL)+ *(fd->anchor) = fn;+ else+ (*(fd->lastptr))->next = fn;+ *(fd->lastptr) = fn;+ }++ /* Handle OP_BINARY_FILES */++ else if (op->type == OP_BINFILES)+ {+ if (strcmp(option_data, "binary") == 0)+ binary_files = BIN_BINARY;+ else if (strcmp(option_data, "without-match") == 0)+ binary_files = BIN_NOMATCH;+ else if (strcmp(option_data, "text") == 0)+ binary_files = BIN_TEXT;+ else+ {+ fprintf(stderr, "pcre2grep: unknown value \"%s\" for binary-files\n",+ option_data);+ pcre2grep_exit(usage(2));+ }+ }++ /* Otherwise, deal with a single string or numeric data value. */++ else if (op->type != OP_NUMBER && op->type != OP_U32NUMBER &&+ op->type != OP_OP_NUMBER && op->type != OP_SIZE)+ {+ *((char **)op->dataptr) = option_data;+ }+ else+ {+ unsigned long int n = decode_number(option_data, op, longop);+ if (op->type == OP_U32NUMBER) *((uint32_t *)op->dataptr) = n;+ else if (op->type == OP_SIZE) *((PCRE2_SIZE *)op->dataptr) = n;+ else *((int *)op->dataptr) = n;+ }+ }++/* Options have been decoded. If -C was used, its value is used as a default+for -A and -B. */++if (both_context > 0)+ {+ if (after_context == 0) after_context = both_context;+ if (before_context == 0) before_context = both_context;+ }++/* Only one of --only-matching, --output, --file-offsets, or --line-offsets is+permitted. They display, each in their own way, only the data that has matched.+*/++only_matching_count = (only_matching != NULL) + (output_text != NULL) ++ file_offsets + line_offsets;++if (only_matching_count > 1)+ {+ fprintf(stderr, "pcre2grep: Cannot mix --only-matching, --output, "+ "--file-offsets and/or --line-offsets\n");+ pcre2grep_exit(usage(2));+ }+++/* Check that there is a big enough ovector for all -o settings. */++for (om = only_matching; om != NULL; om = om->next)+ {+ int n = om->groupnum;+ if (n > (int)capture_max)+ {+ fprintf(stderr, "pcre2grep: Requested group %d cannot be captured.\n", n);+ fprintf(stderr, "pcre2grep: Use --om-capture to increase the size of the capture vector.\n");+ goto EXIT2;+ }+ }++/* Check the text supplied to --output for errors. */++if (output_text != NULL &&+ !syntax_check_output_text((PCRE2_SPTR)output_text, FALSE))+ goto EXIT2;++/* Set up default compile and match contexts and a match data block. */++offset_size = capture_max + 1;+compile_context = pcre2_compile_context_create(NULL);+match_context = pcre2_match_context_create(NULL);+match_data = pcre2_match_data_create(offset_size, NULL);+offsets = pcre2_get_ovector_pointer(match_data);++/* If string (script) callouts are supported, set up the callout processing+function. */++#ifdef SUPPORT_PCRE2GREP_CALLOUT+pcre2_set_callout(match_context, pcre2grep_callout, NULL);+#endif++/* Put limits into the match data block. */++if (heap_limit != PCRE2_UNSET) pcre2_set_heap_limit(match_context, heap_limit);+if (match_limit > 0) pcre2_set_match_limit(match_context, match_limit);+if (depth_limit > 0) pcre2_set_depth_limit(match_context, depth_limit);++/* If a locale has not been provided as an option, see if the LC_CTYPE or+LC_ALL environment variable is set, and if so, use it. */++if (locale == NULL)+ {+ locale = getenv("LC_ALL");+ locale_from = "LC_ALL";+ }++if (locale == NULL)+ {+ locale = getenv("LC_CTYPE");+ locale_from = "LC_CTYPE";+ }++/* If a locale is set, use it to generate the tables the PCRE needs. Passing+NULL to pcre2_maketables() means that malloc() is used to get the memory. */++if (locale != NULL)+ {+ if (setlocale(LC_CTYPE, locale) == NULL)+ {+ fprintf(stderr, "pcre2grep: Failed to set locale %s (obtained from %s)\n",+ locale, locale_from);+ goto EXIT2;+ }+ character_tables = pcre2_maketables(NULL);+ pcre2_set_character_tables(compile_context, character_tables);+ }++/* Sort out colouring */++if (colour_option != NULL && strcmp(colour_option, "never") != 0)+ {+ if (strcmp(colour_option, "always") == 0)+#ifdef WIN32+ do_ansi = !is_stdout_tty(),+#endif+ do_colour = TRUE;+ else if (strcmp(colour_option, "auto") == 0) do_colour = is_stdout_tty();+ else+ {+ fprintf(stderr, "pcre2grep: Unknown colour setting \"%s\"\n",+ colour_option);+ goto EXIT2;+ }+ if (do_colour)+ {+ char *cs = getenv("PCRE2GREP_COLOUR");+ if (cs == NULL) cs = getenv("PCRE2GREP_COLOR");+ if (cs == NULL) cs = getenv("PCREGREP_COLOUR");+ if (cs == NULL) cs = getenv("PCREGREP_COLOR");+ if (cs == NULL) cs = parse_grep_colors(getenv("GREP_COLORS"));+ if (cs == NULL) cs = getenv("GREP_COLOR");+ if (cs != NULL)+ {+ if (strspn(cs, ";0123456789") == strlen(cs)) colour_string = cs;+ }+#ifdef WIN32+ init_colour_output();+#endif+ }+ }++/* Sort out a newline setting. */++if (newline_arg != NULL)+ {+ for (endlinetype = 1; endlinetype < (int)(sizeof(newlines)/sizeof(char *));+ endlinetype++)+ {+ if (strcmpic(newline_arg, newlines[endlinetype]) == 0) break;+ }+ if (endlinetype < (int)(sizeof(newlines)/sizeof(char *)))+ pcre2_set_newline(compile_context, endlinetype);+ else+ {+ fprintf(stderr, "pcre2grep: Invalid newline specifier \"%s\"\n",+ newline_arg);+ goto EXIT2;+ }+ }++/* Find default newline convention */++else+ {+ (void)pcre2_config(PCRE2_CONFIG_NEWLINE, &endlinetype);+ }++/* Interpret the text values for -d and -D */++if (dee_option != NULL)+ {+ if (strcmp(dee_option, "read") == 0) dee_action = dee_READ;+ else if (strcmp(dee_option, "recurse") == 0) dee_action = dee_RECURSE;+ else if (strcmp(dee_option, "skip") == 0) dee_action = dee_SKIP;+ else+ {+ fprintf(stderr, "pcre2grep: Invalid value \"%s\" for -d\n", dee_option);+ goto EXIT2;+ }+ }++if (DEE_option != NULL)+ {+ if (strcmp(DEE_option, "read") == 0) DEE_action = DEE_READ;+ else if (strcmp(DEE_option, "skip") == 0) DEE_action = DEE_SKIP;+ else+ {+ fprintf(stderr, "pcre2grep: Invalid value \"%s\" for -D\n", DEE_option);+ goto EXIT2;+ }+ }++/* Set the extra options */++(void)pcre2_set_compile_extra_options(compile_context, extra_options);++/* Check the values for Jeffrey Friedl's debugging options. */++#ifdef JFRIEDL_DEBUG+if (S_arg > 9)+ {+ fprintf(stderr, "pcre2grep: bad value for -S option\n");+ return 2;+ }+if (jfriedl_XT != 0 || jfriedl_XR != 0)+ {+ if (jfriedl_XT == 0) jfriedl_XT = 1;+ if (jfriedl_XR == 0) jfriedl_XR = 1;+ }+#endif++/* If use_jit is set, check whether JIT is available. If not, do not try+to use JIT. */++if (use_jit)+ {+ uint32_t answer;+ (void)pcre2_config(PCRE2_CONFIG_JIT, &answer);+ if (!answer) use_jit = FALSE;+ }++/* Get memory for the main buffer. */++if (bufthird <= 0)+ {+ fprintf(stderr, "pcre2grep: --buffer-size must be greater than zero\n");+ goto EXIT2;+ }++bufsize = 3*bufthird;+main_buffer = (char *)malloc(bufsize);++if (main_buffer == NULL)+ {+ fprintf(stderr, "pcre2grep: malloc failed\n");+ goto EXIT2;+ }++/* If no patterns were provided by -e, and there are no files provided by -f,+the first argument is the one and only pattern, and it must exist. */++if (patterns == NULL && pattern_files == NULL)+ {+ if (i >= argc) return usage(2);+ patterns = patterns_last = add_pattern(argv[i], (PCRE2_SIZE)strlen(argv[i]),+ NULL);+ i++;+ if (patterns == NULL) goto EXIT2;+ }++/* Compile the patterns that were provided on the command line, either by+multiple uses of -e or as a single unkeyed pattern. We cannot do this until+after all the command-line options are read so that we know which PCRE options+to use. When -F is used, compile_pattern() may add another block into the+chain, so we must not access the next pointer till after the compile. */++for (j = 1, cp = patterns; cp != NULL; j++, cp = cp->next)+ {+ if (!compile_pattern(cp, pcre2_options, FALSE, "command-line",+ (j == 1 && patterns->next == NULL)? 0 : j))+ goto EXIT2;+ }++/* Read and compile the regular expressions that are provided in files. */++for (fn = pattern_files; fn != NULL; fn = fn->next)+ {+ if (!read_pattern_file(fn->name, &patterns, &patterns_last)) goto EXIT2;+ }++/* Unless JIT has been explicitly disabled, arrange a stack for it to use. */++#ifdef SUPPORT_PCRE2GREP_JIT+if (use_jit)+ {+ jit_stack = pcre2_jit_stack_create(32*1024, 1024*1024, NULL);+ if (jit_stack != NULL )+ pcre2_jit_stack_assign(match_context, NULL, jit_stack);+ }+#endif++/* -F, -w, and -x do not apply to include or exclude patterns, so we must+adjust the options. */++pcre2_options &= ~PCRE2_LITERAL;+(void)pcre2_set_compile_extra_options(compile_context, 0);++/* If there are include or exclude patterns read from the command line, compile+them. */++for (j = 0; j < 4; j++)+ {+ int k;+ for (k = 1, cp = *(incexlist[j]); cp != NULL; k++, cp = cp->next)+ {+ if (!compile_pattern(cp, pcre2_options, FALSE, incexname[j],+ (k == 1 && cp->next == NULL)? 0 : k))+ goto EXIT2;+ }+ }++/* Read and compile include/exclude patterns from files. */++for (fn = include_from; fn != NULL; fn = fn->next)+ {+ if (!read_pattern_file(fn->name, &include_patterns, &include_patterns_last))+ goto EXIT2;+ }++for (fn = exclude_from; fn != NULL; fn = fn->next)+ {+ if (!read_pattern_file(fn->name, &exclude_patterns, &exclude_patterns_last))+ goto EXIT2;+ }++/* If there are no files that contain lists of files to search, and there are+no file arguments, search stdin, and then exit. */++if (file_lists == NULL && i >= argc)+ {+ rc = pcre2grep(stdin, FR_PLAIN, stdin_name,+ (filenames > FN_DEFAULT)? stdin_name : NULL);+ goto EXIT;+ }++/* If any files that contains a list of files to search have been specified,+read them line by line and search the given files. */++for (fn = file_lists; fn != NULL; fn = fn->next)+ {+ char buffer[FNBUFSIZ];+ FILE *fl;+ if (strcmp(fn->name, "-") == 0) fl = stdin; else+ {+ fl = fopen(fn->name, "rb");+ if (fl == NULL)+ {+ fprintf(stderr, "pcre2grep: Failed to open %s: %s\n", fn->name,+ strerror(errno));+ goto EXIT2;+ }+ }+ while (fgets(buffer, sizeof(buffer), fl) != NULL)+ {+ int frc;+ char *end = buffer + (int)strlen(buffer);+ while (end > buffer && isspace(end[-1])) end--;+ *end = 0;+ if (*buffer != 0)+ {+ frc = grep_or_recurse(buffer, dee_action == dee_RECURSE, FALSE);+ if (frc > 1) rc = frc;+ else if (frc == 0 && rc == 1) rc = 0;+ }+ }+ if (fl != stdin) fclose(fl);+ }++/* After handling file-list, work through remaining arguments. Pass in the fact+that there is only one argument at top level - this suppresses the file name if+the argument is not a directory and filenames are not otherwise forced. */++only_one_at_top = i == argc - 1 && file_lists == NULL;++for (; i < argc; i++)+ {+ int frc = grep_or_recurse(argv[i], dee_action == dee_RECURSE,+ only_one_at_top);+ if (frc > 1) rc = frc;+ else if (frc == 0 && rc == 1) rc = 0;+ }++#ifdef SUPPORT_PCRE2GREP_CALLOUT+/* If separating builtin echo callouts by implicit newline, add one more for+the final item. */++if (om_separator != NULL && strcmp(om_separator, STDOUT_NL) == 0)+ fprintf(stdout, STDOUT_NL);+#endif++/* Show the total number of matches if requested, but not if only one file's+count was printed. */++if (show_total_count && counts_printed != 1 && filenames != FN_NOMATCH_ONLY)+ {+ if (counts_printed != 0 && filenames >= FN_DEFAULT)+ fprintf(stdout, "TOTAL:");+ fprintf(stdout, "%lu" STDOUT_NL, total_count);+ }++EXIT:+#ifdef SUPPORT_PCRE2GREP_JIT+pcre2_jit_free_unused_memory(NULL);+if (jit_stack != NULL) pcre2_jit_stack_free(jit_stack);+#endif++free(main_buffer);+if (character_tables != NULL) pcre2_maketables_free(NULL, character_tables);++pcre2_compile_context_free(compile_context);+pcre2_match_context_free(match_context);+pcre2_match_data_free(match_data);++free_pattern_chain(patterns);+free_pattern_chain(include_patterns);+free_pattern_chain(include_dir_patterns);+free_pattern_chain(exclude_patterns);+free_pattern_chain(exclude_dir_patterns);++free_file_chain(exclude_from);+free_file_chain(include_from);+free_file_chain(pattern_files);+free_file_chain(file_lists);++while (only_matching != NULL)+ {+ omstr *this = only_matching;+ only_matching = this->next;+ free(this);+ }++pcre2grep_exit(rc);++EXIT2:+rc = 2;+goto EXIT;+}++/* End of pcre2grep */
+ src/c/pcre2/src/pcre2posix.c view
@@ -0,0 +1,423 @@+/*************************************************+* 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) 2016-2019 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.+-----------------------------------------------------------------------------+*/+++/* This module is a wrapper that provides a POSIX API to the underlying PCRE2+functions. The operative functions are called pcre2_regcomp(), etc., with+wrappers that use the plain POSIX names. In addition, pcre2posix.h defines the+POSIX names as macros for the pcre2_xxx functions, so any program that includes+it and uses the POSIX names will call the base functions directly. This makes+it easier for an application to be sure it gets the PCRE2 versions in the+presence of other POSIX regex libraries. */+++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif+++/* Ensure that the PCRE2POSIX_EXP_xxx macros are set appropriately for+compiling these functions. This must come before including pcre2posix.h, where+they are set for an application (using these functions) if they have not+previously been set. */++#if defined(_WIN32) && !defined(PCRE2_STATIC)+# define PCRE2POSIX_EXP_DECL extern __declspec(dllexport)+# define PCRE2POSIX_EXP_DEFN __declspec(dllexport)+#endif++/* Older versions of MSVC lack snprintf(). This define allows for+warning/error-free compilation and testing with MSVC compilers back to at least+MSVC 10/2010. Except for VC6 (which is missing some fundamentals and fails). */++#if defined(_MSC_VER) && (_MSC_VER < 1900)+#define snprintf _snprintf+#endif+++/* Compile-time error numbers start at this value. It should probably never be+changed. This #define is a copy of the one in pcre2_internal.h. */++#define COMPILE_ERROR_BASE 100+++/* Standard C headers */++#include <ctype.h>+#include <limits.h>+#include <stddef.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>++/* PCRE2 headers */++#include "pcre2.h"+#include "pcre2posix.h"++/* When compiling with the MSVC compiler, it is sometimes necessary to include+a "calling convention" before exported function names. (This is secondhand+information; I know nothing about MSVC myself). For example, something like++ void __cdecl function(....)++might be needed. In order to make this easy, all the exported functions have+PCRE2_CALL_CONVENTION just before their names. It is rarely needed; if not+set, we ensure here that it has no effect. */++#ifndef PCRE2_CALL_CONVENTION+#define PCRE2_CALL_CONVENTION+#endif++/* Table to translate PCRE2 compile time error codes into POSIX error codes.+Only a few PCRE2 errors with a value greater than 23 turn into special POSIX+codes: most go to REG_BADPAT. The second table lists, in pairs, those that+don't. */++static const int eint1[] = {+ 0, /* No error */+ REG_EESCAPE, /* \ at end of pattern */+ REG_EESCAPE, /* \c at end of pattern */+ REG_EESCAPE, /* unrecognized character follows \ */+ REG_BADBR, /* numbers out of order in {} quantifier */+ /* 5 */+ REG_BADBR, /* number too big in {} quantifier */+ REG_EBRACK, /* missing terminating ] for character class */+ REG_ECTYPE, /* invalid escape sequence in character class */+ REG_ERANGE, /* range out of order in character class */+ REG_BADRPT, /* nothing to repeat */+ /* 10 */+ REG_ASSERT, /* internal error: unexpected repeat */+ REG_BADPAT, /* unrecognized character after (? or (?- */+ REG_BADPAT, /* POSIX named classes are supported only within a class */+ REG_BADPAT, /* POSIX collating elements are not supported */+ REG_EPAREN, /* missing ) */+ /* 15 */+ REG_ESUBREG, /* reference to non-existent subpattern */+ REG_INVARG, /* pattern passed as NULL */+ REG_INVARG, /* unknown compile-time option bit(s) */+ REG_EPAREN, /* missing ) after (?# comment */+ REG_ESIZE, /* parentheses nested too deeply */+ /* 20 */+ REG_ESIZE, /* regular expression too large */+ REG_ESPACE, /* failed to get memory */+ REG_EPAREN, /* unmatched closing parenthesis */+ REG_ASSERT /* internal error: code overflow */+ };++static const int eint2[] = {+ 30, REG_ECTYPE, /* unknown POSIX class name */+ 32, REG_INVARG, /* this version of PCRE2 does not have Unicode support */+ 37, REG_EESCAPE, /* PCRE2 does not support \L, \l, \N{name}, \U, or \u */+ 56, REG_INVARG, /* internal error: unknown newline setting */+ 92, REG_INVARG, /* invalid option bits with PCRE2_LITERAL */+};++/* Table of texts corresponding to POSIX error codes */++static const char *const pstring[] = {+ "", /* Dummy for value 0 */+ "internal error", /* REG_ASSERT */+ "invalid repeat counts in {}", /* BADBR */+ "pattern error", /* BADPAT */+ "? * + invalid", /* BADRPT */+ "unbalanced {}", /* EBRACE */+ "unbalanced []", /* EBRACK */+ "collation error - not relevant", /* ECOLLATE */+ "bad class", /* ECTYPE */+ "bad escape sequence", /* EESCAPE */+ "empty expression", /* EMPTY */+ "unbalanced ()", /* EPAREN */+ "bad range inside []", /* ERANGE */+ "expression too big", /* ESIZE */+ "failed to get memory", /* ESPACE */+ "bad back reference", /* ESUBREG */+ "bad argument", /* INVARG */+ "match failed" /* NOMATCH */+};++++/*************************************************+* Wrappers with traditional POSIX names *+*************************************************/++/* Keep defining them to preseve the ABI for applications linked to the pcre2+POSIX library before these names were changed into macros in pcre2posix.h.+This also ensures that the POSIX names are callable from languages that do not+include pcre2posix.h. It is vital to #undef the macro definitions from+pcre2posix.h! */++#undef regerror+PCRE2POSIX_EXP_DECL size_t regerror(int, const regex_t *, char *, size_t);+PCRE2POSIX_EXP_DEFN size_t PCRE2_CALL_CONVENTION+regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)+{+return pcre2_regerror(errcode, preg, errbuf, errbuf_size);+}++#undef regfree+PCRE2POSIX_EXP_DECL void regfree(regex_t *);+PCRE2POSIX_EXP_DEFN void PCRE2_CALL_CONVENTION+regfree(regex_t *preg)+{+pcre2_regfree(preg);+}++#undef regcomp+PCRE2POSIX_EXP_DECL int regcomp(regex_t *, const char *, int);+PCRE2POSIX_EXP_DEFN int PCRE2_CALL_CONVENTION+regcomp(regex_t *preg, const char *pattern, int cflags)+{+return pcre2_regcomp(preg, pattern, cflags);+}++#undef regexec+PCRE2POSIX_EXP_DECL int regexec(const regex_t *, const char *, size_t,+ regmatch_t *, int);+PCRE2POSIX_EXP_DEFN int PCRE2_CALL_CONVENTION+regexec(const regex_t *preg, const char *string, size_t nmatch,+ regmatch_t pmatch[], int eflags)+{+return pcre2_regexec(preg, string, nmatch, pmatch, eflags);+}++++/*************************************************+* Translate error code to string *+*************************************************/++PCRE2POSIX_EXP_DEFN size_t PCRE2_CALL_CONVENTION+pcre2_regerror(int errcode, const regex_t *preg, char *errbuf,+ size_t errbuf_size)+{+int used;+const char *message;++message = (errcode <= 0 || errcode >= (int)(sizeof(pstring)/sizeof(char *)))?+ "unknown error code" : pstring[errcode];++if (preg != NULL && (int)preg->re_erroffset != -1)+ {+ used = snprintf(errbuf, errbuf_size, "%s at offset %-6d", message,+ (int)preg->re_erroffset);+ }+else+ {+ used = snprintf(errbuf, errbuf_size, "%s", message);+ }++return used + 1;+}++++/*************************************************+* Free store held by a regex *+*************************************************/++PCRE2POSIX_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_regfree(regex_t *preg)+{+pcre2_match_data_free(preg->re_match_data);+pcre2_code_free(preg->re_pcre2_code);+}++++/*************************************************+* Compile a regular expression *+*************************************************/++/*+Arguments:+ preg points to a structure for recording the compiled expression+ pattern the pattern to compile+ cflags compilation flags++Returns: 0 on success+ various non-zero codes on failure+*/++PCRE2POSIX_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_regcomp(regex_t *preg, const char *pattern, int cflags)+{+PCRE2_SIZE erroffset;+PCRE2_SIZE patlen;+int errorcode;+int options = 0;+int re_nsub = 0;++patlen = ((cflags & REG_PEND) != 0)? (PCRE2_SIZE)(preg->re_endp - pattern) :+ PCRE2_ZERO_TERMINATED;++if ((cflags & REG_ICASE) != 0) options |= PCRE2_CASELESS;+if ((cflags & REG_NEWLINE) != 0) options |= PCRE2_MULTILINE;+if ((cflags & REG_DOTALL) != 0) options |= PCRE2_DOTALL;+if ((cflags & REG_NOSPEC) != 0) options |= PCRE2_LITERAL;+if ((cflags & REG_UTF) != 0) options |= PCRE2_UTF;+if ((cflags & REG_UCP) != 0) options |= PCRE2_UCP;+if ((cflags & REG_UNGREEDY) != 0) options |= PCRE2_UNGREEDY;++preg->re_cflags = cflags;+preg->re_pcre2_code = pcre2_compile((PCRE2_SPTR)pattern, patlen, options,+ &errorcode, &erroffset, NULL);+preg->re_erroffset = erroffset;++if (preg->re_pcre2_code == NULL)+ {+ unsigned int i;++ /* A negative value is a UTF error; otherwise all error codes are greater+ than COMPILE_ERROR_BASE, but check, just in case. */++ if (errorcode < COMPILE_ERROR_BASE) return REG_BADPAT;+ errorcode -= COMPILE_ERROR_BASE;++ if (errorcode < (int)(sizeof(eint1)/sizeof(const int)))+ return eint1[errorcode];+ for (i = 0; i < sizeof(eint2)/sizeof(const int); i += 2)+ if (errorcode == eint2[i]) return eint2[i+1];+ return REG_BADPAT;+ }++(void)pcre2_pattern_info((const pcre2_code *)preg->re_pcre2_code,+ PCRE2_INFO_CAPTURECOUNT, &re_nsub);+preg->re_nsub = (size_t)re_nsub;+preg->re_match_data = pcre2_match_data_create(re_nsub + 1, NULL);+preg->re_erroffset = (size_t)(-1); /* No meaning after successful compile */++if (preg->re_match_data == NULL)+ {+ pcre2_code_free(preg->re_pcre2_code);+ return REG_ESPACE;+ }++return 0;+}++++/*************************************************+* Match a regular expression *+*************************************************/++/* A suitable match_data block, large enough to hold all possible captures, was+obtained when the pattern was compiled, to save having to allocate and free it+for each match. If REG_NOSUB was specified at compile time, the nmatch and+pmatch arguments are ignored, and the only result is yes/no/error. */++PCRE2POSIX_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_regexec(const regex_t *preg, const char *string, size_t nmatch,+ regmatch_t pmatch[], int eflags)+{+int rc, so, eo;+int options = 0;+pcre2_match_data *md = (pcre2_match_data *)preg->re_match_data;++if ((eflags & REG_NOTBOL) != 0) options |= PCRE2_NOTBOL;+if ((eflags & REG_NOTEOL) != 0) options |= PCRE2_NOTEOL;+if ((eflags & REG_NOTEMPTY) != 0) options |= PCRE2_NOTEMPTY;++/* When REG_NOSUB was specified, or if no vector has been passed in which to+put captured strings, ensure that nmatch is zero. This will stop any attempt to+write to pmatch. */++if ((preg->re_cflags & REG_NOSUB) != 0 || pmatch == NULL) nmatch = 0;++/* REG_STARTEND is a BSD extension, to allow for non-NUL-terminated strings.+The man page from OS X says "REG_STARTEND affects only the location of the+string, not how it is matched". That is why the "so" value is used to bump the+start location rather than being passed as a PCRE2 "starting offset". */++if ((eflags & REG_STARTEND) != 0)+ {+ if (pmatch == NULL) return REG_INVARG;+ so = pmatch[0].rm_so;+ eo = pmatch[0].rm_eo;+ }+else+ {+ so = 0;+ eo = (int)strlen(string);+ }++rc = pcre2_match((const pcre2_code *)preg->re_pcre2_code,+ (PCRE2_SPTR)string + so, (eo - so), 0, options, md, NULL);++/* Successful match */++if (rc >= 0)+ {+ size_t i;+ PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(md);+ if ((size_t)rc > nmatch) rc = (int)nmatch;+ for (i = 0; i < (size_t)rc; i++)+ {+ pmatch[i].rm_so = (ovector[i*2] == PCRE2_UNSET)? -1 :+ (int)(ovector[i*2] + so);+ pmatch[i].rm_eo = (ovector[i*2+1] == PCRE2_UNSET)? -1 :+ (int)(ovector[i*2+1] + so);+ }+ for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1;+ return 0;+ }++/* Unsuccessful match */++if (rc <= PCRE2_ERROR_UTF8_ERR1 && rc >= PCRE2_ERROR_UTF8_ERR21)+ return REG_INVARG;++switch(rc)+ {+ default: return REG_ASSERT;+ case PCRE2_ERROR_BADMODE: return REG_INVARG;+ case PCRE2_ERROR_BADMAGIC: return REG_INVARG;+ case PCRE2_ERROR_BADOPTION: return REG_INVARG;+ case PCRE2_ERROR_BADUTFOFFSET: return REG_INVARG;+ case PCRE2_ERROR_MATCHLIMIT: return REG_ESPACE;+ case PCRE2_ERROR_NOMATCH: return REG_NOMATCH;+ case PCRE2_ERROR_NOMEMORY: return REG_ESPACE;+ case PCRE2_ERROR_NULL: return REG_INVARG;+ }+}++/* End of pcre2posix.c */
+ src/c/pcre2/src/pcre2posix.h view
@@ -0,0 +1,170 @@+/*************************************************+* Perl-Compatible Regular Expressions *+*************************************************/++/* PCRE2 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. This is+the public header file to be #included by applications that call PCRE2 via the+POSIX wrapper interface.++ Written by Philip Hazel+ Original API code Copyright (c) 1997-2012 University of Cambridge+ New API code Copyright (c) 2016-2019 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.+-----------------------------------------------------------------------------+*/+++/* Have to include stdlib.h in order to ensure that size_t is defined. */++#include <stdlib.h>++/* Allow for C++ users */++#ifdef __cplusplus+extern "C" {+#endif++/* Options, mostly defined by POSIX, but with some extras. */++#define REG_ICASE 0x0001 /* Maps to PCRE2_CASELESS */+#define REG_NEWLINE 0x0002 /* Maps to PCRE2_MULTILINE */+#define REG_NOTBOL 0x0004 /* Maps to PCRE2_NOTBOL */+#define REG_NOTEOL 0x0008 /* Maps to PCRE2_NOTEOL */+#define REG_DOTALL 0x0010 /* NOT defined by POSIX; maps to PCRE2_DOTALL */+#define REG_NOSUB 0x0020 /* Do not report what was matched */+#define REG_UTF 0x0040 /* NOT defined by POSIX; maps to PCRE2_UTF */+#define REG_STARTEND 0x0080 /* BSD feature: pass subject string by so,eo */+#define REG_NOTEMPTY 0x0100 /* NOT defined by POSIX; maps to PCRE2_NOTEMPTY */+#define REG_UNGREEDY 0x0200 /* NOT defined by POSIX; maps to PCRE2_UNGREEDY */+#define REG_UCP 0x0400 /* NOT defined by POSIX; maps to PCRE2_UCP */+#define REG_PEND 0x0800 /* GNU feature: pass end pattern by re_endp */+#define REG_NOSPEC 0x1000 /* Maps to PCRE2_LITERAL */++/* This is not used by PCRE2, but by defining it we make it easier+to slot PCRE2 into existing programs that make POSIX calls. */++#define REG_EXTENDED 0++/* Error values. Not all these are relevant or used by the wrapper. */++enum {+ REG_ASSERT = 1, /* internal error ? */+ REG_BADBR, /* invalid repeat counts in {} */+ REG_BADPAT, /* pattern error */+ REG_BADRPT, /* ? * + invalid */+ REG_EBRACE, /* unbalanced {} */+ REG_EBRACK, /* unbalanced [] */+ REG_ECOLLATE, /* collation error - not relevant */+ REG_ECTYPE, /* bad class */+ REG_EESCAPE, /* bad escape sequence */+ REG_EMPTY, /* empty expression */+ REG_EPAREN, /* unbalanced () */+ REG_ERANGE, /* bad range inside [] */+ REG_ESIZE, /* expression too big */+ REG_ESPACE, /* failed to get memory */+ REG_ESUBREG, /* bad back reference */+ REG_INVARG, /* bad argument */+ REG_NOMATCH /* match failed */+};+++/* The structure representing a compiled regular expression. It is also used+for passing the pattern end pointer when REG_PEND is set. */++typedef struct {+ void *re_pcre2_code;+ void *re_match_data;+ const char *re_endp;+ size_t re_nsub;+ size_t re_erroffset;+ int re_cflags;+} regex_t;++/* The structure in which a captured offset is returned. */++typedef int regoff_t;++typedef struct {+ regoff_t rm_so;+ regoff_t rm_eo;+} regmatch_t;++/* When an application links to a PCRE2 DLL in Windows, the symbols that are+imported have to be identified as such. When building PCRE2, the appropriate+export settings are needed, and are set in pcre2posix.c before including this+file. */++#if defined(_WIN32) && !defined(PCRE2_STATIC) && !defined(PCRE2POSIX_EXP_DECL)+# define PCRE2POSIX_EXP_DECL extern __declspec(dllimport)+# define PCRE2POSIX_EXP_DEFN __declspec(dllimport)+#endif++/* By default, we use the standard "extern" declarations. */++#ifndef PCRE2POSIX_EXP_DECL+# ifdef __cplusplus+# define PCRE2POSIX_EXP_DECL extern "C"+# define PCRE2POSIX_EXP_DEFN extern "C"+# else+# define PCRE2POSIX_EXP_DECL extern+# define PCRE2POSIX_EXP_DEFN extern+# endif+#endif++/* The functions. The actual code is in functions with pcre2_xxx names for+uniqueness. POSIX names are provided as macros for API compatibility with POSIX+regex functions. It's done this way to ensure to they are always linked from+the PCRE2 library and not by accident from elsewhere (regex_t differs in size+elsewhere). */++PCRE2POSIX_EXP_DECL int pcre2_regcomp(regex_t *, const char *, int);+PCRE2POSIX_EXP_DECL int pcre2_regexec(const regex_t *, const char *, size_t,+ regmatch_t *, int);+PCRE2POSIX_EXP_DECL size_t pcre2_regerror(int, const regex_t *, char *, size_t);+PCRE2POSIX_EXP_DECL void pcre2_regfree(regex_t *);++#define regcomp pcre2_regcomp+#define regexec pcre2_regexec+#define regerror pcre2_regerror+#define regfree pcre2_regfree++/* Debian had a patch that used different names. These are now here to save+them having to maintain their own patch, but are not documented by PCRE2. */++#define PCRE2regcomp pcre2_regcomp+#define PCRE2regexec pcre2_regexec+#define PCRE2regerror pcre2_regerror+#define PCRE2regfree pcre2_regfree++#ifdef __cplusplus+} /* extern "C" */+#endif++/* End of pcre2posix.h */
+ src/c/pcre2/src/pcre2test.c view
@@ -0,0 +1,9220 @@+/*************************************************+* PCRE2 testing program *+*************************************************/++/* PCRE2 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. In 2014+the API was completely revised and '2' was added to the name, because the old+API, which had lasted for 16 years, could not accommodate new requirements. At+the same time, this testing program was re-designed because its original+hacked-up (non-) design had also run out of steam.++ Written by Philip Hazel+ Original code Copyright (c) 1997-2012 University of Cambridge+ Rewritten code Copyright (c) 2016-2020 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.+-----------------------------------------------------------------------------+*/+++/* This program supports testing of the 8-bit, 16-bit, and 32-bit PCRE2+libraries in a single program, though its input and output are always 8-bit.+It is different from modules such as pcre2_compile.c in the library itself,+which are compiled separately for each code unit width. If two widths are+enabled, for example, pcre2_compile.c is compiled twice. In contrast,+pcre2test.c is compiled only once, and linked with all the enabled libraries.+Therefore, it must not make use of any of the macros from pcre2.h or+pcre2_internal.h that depend on PCRE2_CODE_UNIT_WIDTH. It does, however, make+use of SUPPORT_PCRE2_8, SUPPORT_PCRE2_16, and SUPPORT_PCRE2_32, to ensure that+it references only the enabled library functions. */++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include <ctype.h>+#include <stdio.h>+#include <string.h>+#include <stdlib.h>+#include <time.h>+#include <locale.h>+#include <errno.h>++#if defined NATIVE_ZOS+#include "pcrzoscs.h"+/* That header is not included in the main PCRE2 distribution because other+apparatus is needed to compile pcre2test for z/OS. The header can be found in+the special z/OS distribution, which is available from www.zaconsultants.net or+from www.cbttape.org. */+#endif++#ifdef HAVE_UNISTD_H+#include <unistd.h>+#endif++/* Debugging code enabler */++/* #define DEBUG_SHOW_MALLOC_ADDRESSES */++/* Both libreadline and libedit are optionally supported. The user-supplied+original patch uses readline/readline.h for libedit, but in at least one system+it is installed as editline/readline.h, so the configuration code now looks for+that first, falling back to readline/readline.h. */++#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+#if defined(SUPPORT_LIBREADLINE)+#include <readline/readline.h>+#include <readline/history.h>+#else+#if defined(HAVE_EDITLINE_READLINE_H)+#include <editline/readline.h>+#else+#include <readline/readline.h>+#endif+#endif+#endif++/* Put the test for interactive input into a macro so that it can be changed if+required for different environments. */++#define INTERACTIVE(f) isatty(fileno(f))+++/* ---------------------- System-specific definitions ---------------------- */++/* A number of things vary for Windows builds. Originally, pcretest opened its+input and output without "b"; then I was told that "b" was needed in some+environments, so it was added for release 5.0 to both the input and output. (It+makes no difference on Unix-like systems.) Later I was told that it is wrong+for the input on Windows. I've now abstracted the modes into macros that are+set here, to make it easier to fiddle with them, and removed "b" from the input+mode under Windows. The BINARY versions are used when saving/restoring compiled+patterns. */++#if defined(_WIN32) || defined(WIN32)+#include <io.h> /* For _setmode() */+#include <fcntl.h> /* For _O_BINARY */+#define INPUT_MODE "r"+#define OUTPUT_MODE "wb"+#define BINARY_INPUT_MODE "rb"+#define BINARY_OUTPUT_MODE "wb"++#ifndef isatty+#define isatty _isatty /* This is what Windows calls them, I'm told, */+#endif /* though in some environments they seem to */+ /* be already defined, hence the #ifndefs. */+#ifndef fileno+#define fileno _fileno+#endif++/* A user sent this fix for Borland Builder 5 under Windows. */++#ifdef __BORLANDC__+#define _setmode(handle, mode) setmode(handle, mode)+#endif++/* Not Windows */++#else+#include <sys/time.h> /* These two includes are needed */+#include <sys/resource.h> /* for setrlimit(). */+#if defined NATIVE_ZOS /* z/OS uses non-binary I/O */+#define INPUT_MODE "r"+#define OUTPUT_MODE "w"+#define BINARY_INPUT_MODE "rb"+#define BINARY_OUTPUT_MODE "wb"+#else+#define INPUT_MODE "rb"+#define OUTPUT_MODE "wb"+#define BINARY_INPUT_MODE "rb"+#define BINARY_OUTPUT_MODE "wb"+#endif+#endif++/* VMS-specific code was included as suggested by a VMS user [1]. Another VMS+user [2] provided alternative code which worked better for him. I have+commented out the original, but kept it around just in case. */++#ifdef __VMS+#include <ssdef.h>+/* These two includes came from [2]. */+#include descrip+#include lib$routines+/* void vms_setsymbol( char *, char *, int ); Original code from [1]. */+#endif++/* VC and older compilers don't support %td or %zu, and even some that claim to+be C99 don't support it (hence DISABLE_PERCENT_ZT). There are some non-C99+environments where %lu gives a warning with 32-bit pointers. As there doesn't+seem to be an easy way round this, just live with it (the cases are rare). */++#if defined(_MSC_VER) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L || defined(DISABLE_PERCENT_ZT)+#define PTR_FORM "lu"+#define SIZ_FORM "lu"+#define SIZ_CAST (unsigned long int)+#else+#define PTR_FORM "td"+#define SIZ_FORM "zu"+#define SIZ_CAST+#endif++/* ------------------End of system-specific definitions -------------------- */++/* Glueing macros that are used in several places below. */++#define glue(a,b) a##b+#define G(a,b) glue(a,b)++/* Miscellaneous parameters and manifests */++#ifndef CLOCKS_PER_SEC+#ifdef CLK_TCK+#define CLOCKS_PER_SEC CLK_TCK+#else+#define CLOCKS_PER_SEC 100+#endif+#endif++#define CFORE_UNSET UINT32_MAX /* Unset value for startend/cfail/cerror fields */+#define CONVERT_UNSET UINT32_MAX /* Unset value for convert_type field */+#define DFA_WS_DIMENSION 1000 /* Size of DFA workspace */+#define DEFAULT_OVECCOUNT 15 /* Default ovector count */+#define JUNK_OFFSET 0xdeadbeef /* For initializing ovector */+#define LOCALESIZE 32 /* Size of locale name */+#define LOOPREPEAT 500000 /* Default loop count for timing */+#define MALLOCLISTSIZE 20 /* For remembering mallocs */+#define PARENS_NEST_DEFAULT 220 /* Default parentheses nest limit */+#define PATSTACKSIZE 20 /* Pattern stack for save/restore testing */+#define REPLACE_MODSIZE 100 /* Field for reading 8-bit replacement */+#define VERSION_SIZE 64 /* Size of buffer for the version strings */++/* Default JIT compile options */++#define JIT_DEFAULT (PCRE2_JIT_COMPLETE|\+ PCRE2_JIT_PARTIAL_SOFT|\+ PCRE2_JIT_PARTIAL_HARD)++/* Make sure the buffer into which replacement strings are copied is big enough+to hold them as 32-bit code units. */++#define REPLACE_BUFFSIZE 1024 /* This is a byte value */++/* Execution modes */++#define PCRE8_MODE 8+#define PCRE16_MODE 16+#define PCRE32_MODE 32++/* Processing returns */++enum { PR_OK, PR_SKIP, PR_ABEND };++/* The macro PRINTABLE determines whether to print an output character as-is or+as a hex value when showing compiled patterns. is We use it in cases when the+locale has not been explicitly changed, so as to get consistent output from+systems that differ in their output from isprint() even in the "C" locale. */++#ifdef EBCDIC+#define PRINTABLE(c) ((c) >= 64 && (c) < 255)+#else+#define PRINTABLE(c) ((c) >= 32 && (c) < 127)+#endif++#define PRINTOK(c) ((use_tables != NULL && c < 256)? isprint(c) : PRINTABLE(c))++/* We have to include some of the library source files because we need+to use some of the macros, internal structure definitions, and other internal+values - pcre2test has "inside information" compared to an application program+that strictly follows the PCRE2 API.++Before including pcre2_internal.h we define PRIV so that it does not get+defined therein. This ensures that PRIV names in the included files do not+clash with those in the libraries. Also, although pcre2_internal.h does itself+include pcre2.h, we explicitly include it beforehand, along with pcre2posix.h,+so that the PCRE2_EXP_xxx macros get set appropriately for an application, not+for building the library. */++#define PRIV(name) name+#define PCRE2_CODE_UNIT_WIDTH 0+#include "pcre2.h"+#include "pcre2posix.h"+#include "pcre2_internal.h"++/* We need access to some of the data tables that PCRE2 uses. Defining+PCRE2_PCRETEST makes some minor changes in the files. The previous definition+of PRIV avoids name clashes. */++#define PCRE2_PCRE2TEST+#include "pcre2_tables.c"+#include "pcre2_ucd.c"++/* 32-bit integer values in the input are read by strtoul() or strtol(). The+check needed for overflow depends on whether long ints are in fact longer than+ints. They are defined not to be shorter. */++#if ULONG_MAX > UINT32_MAX+#define U32OVERFLOW(x) (x > UINT32_MAX)+#else+#define U32OVERFLOW(x) (x == UINT32_MAX)+#endif++#if LONG_MAX > INT32_MAX+#define S32OVERFLOW(x) (x > INT32_MAX || x < INT32_MIN)+#else+#define S32OVERFLOW(x) (x == INT32_MAX || x == INT32_MIN)+#endif++/* When PCRE2_CODE_UNIT_WIDTH is zero, pcre2_internal.h does not include+pcre2_intmodedep.h, which is where mode-dependent macros and structures are+defined. We can now include it for each supported code unit width. Because+PCRE2_CODE_UNIT_WIDTH was defined as zero before including pcre2.h, it will+have left PCRE2_SUFFIX defined as a no-op. We must re-define it appropriately+while including these files, and then restore it to a no-op. Because LINK_SIZE+may be changed in 16-bit mode and forced to 1 in 32-bit mode, the order of+these inclusions should not be changed. */++#undef PCRE2_SUFFIX+#undef PCRE2_CODE_UNIT_WIDTH++#ifdef SUPPORT_PCRE2_8+#define PCRE2_CODE_UNIT_WIDTH 8+#define PCRE2_SUFFIX(a) G(a,8)+#include "pcre2_intmodedep.h"+#include "pcre2_printint.c"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SUFFIX+#endif /* SUPPORT_PCRE2_8 */++#ifdef SUPPORT_PCRE2_16+#define PCRE2_CODE_UNIT_WIDTH 16+#define PCRE2_SUFFIX(a) G(a,16)+#include "pcre2_intmodedep.h"+#include "pcre2_printint.c"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SUFFIX+#endif /* SUPPORT_PCRE2_16 */++#ifdef SUPPORT_PCRE2_32+#define PCRE2_CODE_UNIT_WIDTH 32+#define PCRE2_SUFFIX(a) G(a,32)+#include "pcre2_intmodedep.h"+#include "pcre2_printint.c"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SUFFIX+#endif /* SUPPORT_PCRE2_32 */++#define PCRE2_SUFFIX(a) a++/* We need to be able to check input text for UTF-8 validity, whatever code+widths are actually available, because the input to pcre2test is always in+8-bit code units. So we include the UTF validity checking function for 8-bit+code units. */++extern int valid_utf(PCRE2_SPTR8, PCRE2_SIZE, PCRE2_SIZE *);++#define PCRE2_CODE_UNIT_WIDTH 8+#undef PCRE2_SPTR+#define PCRE2_SPTR PCRE2_SPTR8+#include "pcre2_valid_utf.c"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SPTR++/* If we have 8-bit support, default to it; if there is also 16-or 32-bit+support, it can be selected by a command-line option. If there is no 8-bit+support, there must be 16-bit or 32-bit support, so default to one of them. The+config function, JIT stack, contexts, and version string are the same in all+modes, so use the form of the first that is available. */++#if defined SUPPORT_PCRE2_8+#define DEFAULT_TEST_MODE PCRE8_MODE+#define VERSION_TYPE PCRE2_UCHAR8+#define PCRE2_CONFIG pcre2_config_8+#define PCRE2_JIT_STACK pcre2_jit_stack_8+#define PCRE2_REAL_GENERAL_CONTEXT pcre2_real_general_context_8+#define PCRE2_REAL_COMPILE_CONTEXT pcre2_real_compile_context_8+#define PCRE2_REAL_CONVERT_CONTEXT pcre2_real_convert_context_8+#define PCRE2_REAL_MATCH_CONTEXT pcre2_real_match_context_8++#elif defined SUPPORT_PCRE2_16+#define DEFAULT_TEST_MODE PCRE16_MODE+#define VERSION_TYPE PCRE2_UCHAR16+#define PCRE2_CONFIG pcre2_config_16+#define PCRE2_JIT_STACK pcre2_jit_stack_16+#define PCRE2_REAL_GENERAL_CONTEXT pcre2_real_general_context_16+#define PCRE2_REAL_COMPILE_CONTEXT pcre2_real_compile_context_16+#define PCRE2_REAL_CONVERT_CONTEXT pcre2_real_convert_context_16+#define PCRE2_REAL_MATCH_CONTEXT pcre2_real_match_context_16++#elif defined SUPPORT_PCRE2_32+#define DEFAULT_TEST_MODE PCRE32_MODE+#define VERSION_TYPE PCRE2_UCHAR32+#define PCRE2_CONFIG pcre2_config_32+#define PCRE2_JIT_STACK pcre2_jit_stack_32+#define PCRE2_REAL_GENERAL_CONTEXT pcre2_real_general_context_32+#define PCRE2_REAL_COMPILE_CONTEXT pcre2_real_compile_context_32+#define PCRE2_REAL_CONVERT_CONTEXT pcre2_real_convert_context_32+#define PCRE2_REAL_MATCH_CONTEXT pcre2_real_match_context_32+#endif++/* ------------- Structure and table for handling #-commands ------------- */++typedef struct cmdstruct {+ const char *name;+ int value;+} cmdstruct;++enum { CMD_FORBID_UTF, CMD_LOAD, CMD_LOADTABLES, CMD_NEWLINE_DEFAULT,+ CMD_PATTERN, CMD_PERLTEST, CMD_POP, CMD_POPCOPY, CMD_SAVE, CMD_SUBJECT,+ CMD_UNKNOWN };++static cmdstruct cmdlist[] = {+ { "forbid_utf", CMD_FORBID_UTF },+ { "load", CMD_LOAD },+ { "loadtables", CMD_LOADTABLES },+ { "newline_default", CMD_NEWLINE_DEFAULT },+ { "pattern", CMD_PATTERN },+ { "perltest", CMD_PERLTEST },+ { "pop", CMD_POP },+ { "popcopy", CMD_POPCOPY },+ { "save", CMD_SAVE },+ { "subject", CMD_SUBJECT }};++#define cmdlistcount (sizeof(cmdlist)/sizeof(cmdstruct))++/* ------------- Structures and tables for handling modifiers -------------- */++/* Table of names for newline types. Must be kept in step with the definitions+of PCRE2_NEWLINE_xx in pcre2.h. */++static const char *newlines[] = {+ "DEFAULT", "CR", "LF", "CRLF", "ANY", "ANYCRLF", "NUL" };++/* Structure and table for handling pattern conversion types. */++typedef struct convertstruct {+ const char *name;+ uint32_t option;+} convertstruct;++static convertstruct convertlist[] = {+ { "glob", PCRE2_CONVERT_GLOB },+ { "glob_no_starstar", PCRE2_CONVERT_GLOB_NO_STARSTAR },+ { "glob_no_wild_separator", PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR },+ { "posix_basic", PCRE2_CONVERT_POSIX_BASIC },+ { "posix_extended", PCRE2_CONVERT_POSIX_EXTENDED },+ { "unset", CONVERT_UNSET }};++#define convertlistcount (sizeof(convertlist)/sizeof(convertstruct))++/* Modifier types and applicability */++enum { MOD_CTC, /* Applies to a compile context */+ MOD_CTM, /* Applies to a match context */+ MOD_PAT, /* Applies to a pattern */+ MOD_PATP, /* Ditto, OK for Perl test */+ MOD_DAT, /* Applies to a data line */+ MOD_PD, /* Applies to a pattern or a data line */+ MOD_PDP, /* As MOD_PD, OK for Perl test */+ MOD_PND, /* As MOD_PD, but not for a default pattern */+ MOD_PNDP, /* As MOD_PND, OK for Perl test */+ MOD_CHR, /* Is a single character */+ MOD_CON, /* Is a "convert" type/options list */+ MOD_CTL, /* Is a control bit */+ MOD_BSR, /* Is a BSR value */+ MOD_IN2, /* Is one or two unsigned integers */+ MOD_INS, /* Is a signed integer */+ MOD_INT, /* Is an unsigned integer */+ MOD_IND, /* Is an unsigned integer, but no value => default */+ MOD_NL, /* Is a newline value */+ MOD_NN, /* Is a number or a name; more than one may occur */+ MOD_OPT, /* Is an option bit */+ MOD_SIZ, /* Is a PCRE2_SIZE value */+ MOD_STR }; /* Is a string */++/* Control bits. Some apply to compiling, some to matching, but some can be set+either on a pattern or a data line, so they must all be distinct. There are now+so many of them that they are split into two fields. */++#define CTL_AFTERTEXT 0x00000001u+#define CTL_ALLAFTERTEXT 0x00000002u+#define CTL_ALLCAPTURES 0x00000004u+#define CTL_ALLUSEDTEXT 0x00000008u+#define CTL_ALTGLOBAL 0x00000010u+#define CTL_BINCODE 0x00000020u+#define CTL_CALLOUT_CAPTURE 0x00000040u+#define CTL_CALLOUT_INFO 0x00000080u+#define CTL_CALLOUT_NONE 0x00000100u+#define CTL_DFA 0x00000200u+#define CTL_EXPAND 0x00000400u+#define CTL_FINDLIMITS 0x00000800u+#define CTL_FRAMESIZE 0x00001000u+#define CTL_FULLBINCODE 0x00002000u+#define CTL_GETALL 0x00004000u+#define CTL_GLOBAL 0x00008000u+#define CTL_HEXPAT 0x00010000u /* Same word as USE_LENGTH */+#define CTL_INFO 0x00020000u+#define CTL_JITFAST 0x00040000u+#define CTL_JITVERIFY 0x00080000u+#define CTL_MARK 0x00100000u+#define CTL_MEMORY 0x00200000u+#define CTL_NULLCONTEXT 0x00400000u+#define CTL_POSIX 0x00800000u+#define CTL_POSIX_NOSUB 0x01000000u+#define CTL_PUSH 0x02000000u /* These three must be */+#define CTL_PUSHCOPY 0x04000000u /* all in the same */+#define CTL_PUSHTABLESCOPY 0x08000000u /* word. */+#define CTL_STARTCHAR 0x10000000u+#define CTL_USE_LENGTH 0x20000000u /* Same word as HEXPAT */+#define CTL_UTF8_INPUT 0x40000000u+#define CTL_ZERO_TERMINATE 0x80000000u++/* Combinations */++#define CTL_DEBUG (CTL_FULLBINCODE|CTL_INFO) /* For setting */+#define CTL_ANYINFO (CTL_DEBUG|CTL_BINCODE|CTL_CALLOUT_INFO)+#define CTL_ANYGLOB (CTL_ALTGLOBAL|CTL_GLOBAL)++/* Second control word */++#define CTL2_SUBSTITUTE_CALLOUT 0x00000001u+#define CTL2_SUBSTITUTE_EXTENDED 0x00000002u+#define CTL2_SUBSTITUTE_LITERAL 0x00000004u+#define CTL2_SUBSTITUTE_MATCHED 0x00000008u+#define CTL2_SUBSTITUTE_OVERFLOW_LENGTH 0x00000010u+#define CTL2_SUBSTITUTE_REPLACEMENT_ONLY 0x00000020u+#define CTL2_SUBSTITUTE_UNKNOWN_UNSET 0x00000040u+#define CTL2_SUBSTITUTE_UNSET_EMPTY 0x00000080u+#define CTL2_SUBJECT_LITERAL 0x00000100u+#define CTL2_CALLOUT_NO_WHERE 0x00000200u+#define CTL2_CALLOUT_EXTRA 0x00000400u+#define CTL2_ALLVECTOR 0x00000800u++#define CTL2_NL_SET 0x40000000u /* Informational */+#define CTL2_BSR_SET 0x80000000u /* Informational */++/* These are the matching controls that may be set either on a pattern or on a+data line. They are copied from the pattern controls as initial settings for+data line controls. Note that CTL_MEMORY is not included here, because it does+different things in the two cases. */++#define CTL_ALLPD (CTL_AFTERTEXT|\+ CTL_ALLAFTERTEXT|\+ CTL_ALLCAPTURES|\+ CTL_ALLUSEDTEXT|\+ CTL_ALTGLOBAL|\+ CTL_GLOBAL|\+ CTL_MARK|\+ CTL_STARTCHAR|\+ CTL_UTF8_INPUT)++#define CTL2_ALLPD (CTL2_SUBSTITUTE_CALLOUT|\+ CTL2_SUBSTITUTE_EXTENDED|\+ CTL2_SUBSTITUTE_LITERAL|\+ CTL2_SUBSTITUTE_MATCHED|\+ CTL2_SUBSTITUTE_OVERFLOW_LENGTH|\+ CTL2_SUBSTITUTE_REPLACEMENT_ONLY|\+ CTL2_SUBSTITUTE_UNKNOWN_UNSET|\+ CTL2_SUBSTITUTE_UNSET_EMPTY|\+ CTL2_ALLVECTOR)++/* Structures for holding modifier information for patterns and subject strings+(data). Fields containing modifiers that can be set either for a pattern or a+subject must be at the start and in the same order in both cases so that the+same offset in the big table below works for both. */++typedef struct patctl { /* Structure for pattern modifiers. */+ uint32_t options; /* Must be in same position as datctl */+ uint32_t control; /* Must be in same position as datctl */+ uint32_t control2; /* Must be in same position as datctl */+ uint32_t jitstack; /* Must be in same position as datctl */+ uint8_t replacement[REPLACE_MODSIZE]; /* So must this */+ uint32_t substitute_skip; /* Must be in same position as patctl */+ uint32_t substitute_stop; /* Must be in same position as patctl */+ uint32_t jit;+ uint32_t stackguard_test;+ uint32_t tables_id;+ uint32_t convert_type;+ uint32_t convert_length;+ uint32_t convert_glob_escape;+ uint32_t convert_glob_separator;+ uint32_t regerror_buffsize;+ uint8_t locale[LOCALESIZE];+} patctl;++#define MAXCPYGET 10+#define LENCPYGET 64++typedef struct datctl { /* Structure for data line modifiers. */+ uint32_t options; /* Must be in same position as patctl */+ uint32_t control; /* Must be in same position as patctl */+ uint32_t control2; /* Must be in same position as patctl */+ uint32_t jitstack; /* Must be in same position as patctl */+ uint8_t replacement[REPLACE_MODSIZE]; /* So must this */+ uint32_t substitute_skip; /* Must be in same position as patctl */+ uint32_t substitute_stop; /* Must be in same position as patctl */+ uint32_t startend[2];+ uint32_t cerror[2];+ uint32_t cfail[2];+ int32_t callout_data;+ int32_t copy_numbers[MAXCPYGET];+ int32_t get_numbers[MAXCPYGET];+ uint32_t oveccount;+ uint32_t offset;+ uint8_t copy_names[LENCPYGET];+ uint8_t get_names[LENCPYGET];+} datctl;++/* Ids for which context to modify. */++enum { CTX_PAT, /* Active pattern context */+ CTX_POPPAT, /* Ditto, for a popped pattern */+ CTX_DEFPAT, /* Default pattern context */+ CTX_DAT, /* Active data (match) context */+ CTX_DEFDAT }; /* Default data (match) context */++/* Macros to simplify the big table below. */++#define CO(name) offsetof(PCRE2_REAL_COMPILE_CONTEXT, name)+#define MO(name) offsetof(PCRE2_REAL_MATCH_CONTEXT, name)+#define PO(name) offsetof(patctl, name)+#define PD(name) PO(name)+#define DO(name) offsetof(datctl, name)++/* Table of all long-form modifiers. Must be in collating sequence of modifier+name because it is searched by binary chop. */++typedef struct modstruct {+ const char *name;+ uint16_t which;+ uint16_t type;+ uint32_t value;+ PCRE2_SIZE offset;+} modstruct;++static modstruct modlist[] = {+ { "aftertext", MOD_PNDP, MOD_CTL, CTL_AFTERTEXT, PO(control) },+ { "allaftertext", MOD_PNDP, MOD_CTL, CTL_ALLAFTERTEXT, PO(control) },+ { "allcaptures", MOD_PND, MOD_CTL, CTL_ALLCAPTURES, PO(control) },+ { "allow_empty_class", MOD_PAT, MOD_OPT, PCRE2_ALLOW_EMPTY_CLASS, PO(options) },+ { "allow_surrogate_escapes", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES, CO(extra_options) },+ { "allusedtext", MOD_PNDP, MOD_CTL, CTL_ALLUSEDTEXT, PO(control) },+ { "allvector", MOD_PND, MOD_CTL, CTL2_ALLVECTOR, PO(control2) },+ { "alt_bsux", MOD_PAT, MOD_OPT, PCRE2_ALT_BSUX, PO(options) },+ { "alt_circumflex", MOD_PAT, MOD_OPT, PCRE2_ALT_CIRCUMFLEX, PO(options) },+ { "alt_verbnames", MOD_PAT, MOD_OPT, PCRE2_ALT_VERBNAMES, PO(options) },+ { "altglobal", MOD_PND, MOD_CTL, CTL_ALTGLOBAL, PO(control) },+ { "anchored", MOD_PD, MOD_OPT, PCRE2_ANCHORED, PD(options) },+ { "auto_callout", MOD_PAT, MOD_OPT, PCRE2_AUTO_CALLOUT, PO(options) },+ { "bad_escape_is_literal", MOD_CTC, MOD_OPT, PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL, CO(extra_options) },+ { "bincode", MOD_PAT, MOD_CTL, CTL_BINCODE, PO(control) },+ { "bsr", MOD_CTC, MOD_BSR, 0, CO(bsr_convention) },+ { "callout_capture", MOD_DAT, MOD_CTL, CTL_CALLOUT_CAPTURE, DO(control) },+ { "callout_data", MOD_DAT, MOD_INS, 0, DO(callout_data) },+ { "callout_error", MOD_DAT, MOD_IN2, 0, DO(cerror) },+ { "callout_extra", MOD_DAT, MOD_CTL, CTL2_CALLOUT_EXTRA, DO(control2) },+ { "callout_fail", MOD_DAT, MOD_IN2, 0, DO(cfail) },+ { "callout_info", MOD_PAT, MOD_CTL, CTL_CALLOUT_INFO, PO(control) },+ { "callout_no_where", MOD_DAT, MOD_CTL, CTL2_CALLOUT_NO_WHERE, DO(control2) },+ { "callout_none", MOD_DAT, MOD_CTL, CTL_CALLOUT_NONE, DO(control) },+ { "caseless", MOD_PATP, MOD_OPT, PCRE2_CASELESS, PO(options) },+ { "convert", MOD_PAT, MOD_CON, 0, PO(convert_type) },+ { "convert_glob_escape", MOD_PAT, MOD_CHR, 0, PO(convert_glob_escape) },+ { "convert_glob_separator", MOD_PAT, MOD_CHR, 0, PO(convert_glob_separator) },+ { "convert_length", MOD_PAT, MOD_INT, 0, PO(convert_length) },+ { "copy", MOD_DAT, MOD_NN, DO(copy_numbers), DO(copy_names) },+ { "copy_matched_subject", MOD_DAT, MOD_OPT, PCRE2_COPY_MATCHED_SUBJECT, DO(options) },+ { "debug", MOD_PAT, MOD_CTL, CTL_DEBUG, PO(control) },+ { "depth_limit", MOD_CTM, MOD_INT, 0, MO(depth_limit) },+ { "dfa", MOD_DAT, MOD_CTL, CTL_DFA, DO(control) },+ { "dfa_restart", MOD_DAT, MOD_OPT, PCRE2_DFA_RESTART, DO(options) },+ { "dfa_shortest", MOD_DAT, MOD_OPT, PCRE2_DFA_SHORTEST, DO(options) },+ { "dollar_endonly", MOD_PAT, MOD_OPT, PCRE2_DOLLAR_ENDONLY, PO(options) },+ { "dotall", MOD_PATP, MOD_OPT, PCRE2_DOTALL, PO(options) },+ { "dupnames", MOD_PATP, MOD_OPT, PCRE2_DUPNAMES, PO(options) },+ { "endanchored", MOD_PD, MOD_OPT, PCRE2_ENDANCHORED, PD(options) },+ { "escaped_cr_is_lf", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ESCAPED_CR_IS_LF, CO(extra_options) },+ { "expand", MOD_PAT, MOD_CTL, CTL_EXPAND, PO(control) },+ { "extended", MOD_PATP, MOD_OPT, PCRE2_EXTENDED, PO(options) },+ { "extended_more", MOD_PATP, MOD_OPT, PCRE2_EXTENDED_MORE, PO(options) },+ { "extra_alt_bsux", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ALT_BSUX, CO(extra_options) },+ { "find_limits", MOD_DAT, MOD_CTL, CTL_FINDLIMITS, DO(control) },+ { "firstline", MOD_PAT, MOD_OPT, PCRE2_FIRSTLINE, PO(options) },+ { "framesize", MOD_PAT, MOD_CTL, CTL_FRAMESIZE, PO(control) },+ { "fullbincode", MOD_PAT, MOD_CTL, CTL_FULLBINCODE, PO(control) },+ { "get", MOD_DAT, MOD_NN, DO(get_numbers), DO(get_names) },+ { "getall", MOD_DAT, MOD_CTL, CTL_GETALL, DO(control) },+ { "global", MOD_PNDP, MOD_CTL, CTL_GLOBAL, PO(control) },+ { "heap_limit", MOD_CTM, MOD_INT, 0, MO(heap_limit) },+ { "hex", MOD_PAT, MOD_CTL, CTL_HEXPAT, PO(control) },+ { "info", MOD_PAT, MOD_CTL, CTL_INFO, PO(control) },+ { "jit", MOD_PAT, MOD_IND, 7, PO(jit) },+ { "jitfast", MOD_PAT, MOD_CTL, CTL_JITFAST, PO(control) },+ { "jitstack", MOD_PNDP, MOD_INT, 0, PO(jitstack) },+ { "jitverify", MOD_PAT, MOD_CTL, CTL_JITVERIFY, PO(control) },+ { "literal", MOD_PAT, MOD_OPT, PCRE2_LITERAL, PO(options) },+ { "locale", MOD_PAT, MOD_STR, LOCALESIZE, PO(locale) },+ { "mark", MOD_PNDP, MOD_CTL, CTL_MARK, PO(control) },+ { "match_invalid_utf", MOD_PAT, MOD_OPT, PCRE2_MATCH_INVALID_UTF, PO(options) },+ { "match_limit", MOD_CTM, MOD_INT, 0, MO(match_limit) },+ { "match_line", MOD_CTC, MOD_OPT, PCRE2_EXTRA_MATCH_LINE, CO(extra_options) },+ { "match_unset_backref", MOD_PAT, MOD_OPT, PCRE2_MATCH_UNSET_BACKREF, PO(options) },+ { "match_word", MOD_CTC, MOD_OPT, PCRE2_EXTRA_MATCH_WORD, CO(extra_options) },+ { "max_pattern_length", MOD_CTC, MOD_SIZ, 0, CO(max_pattern_length) },+ { "memory", MOD_PD, MOD_CTL, CTL_MEMORY, PD(control) },+ { "multiline", MOD_PATP, MOD_OPT, PCRE2_MULTILINE, PO(options) },+ { "never_backslash_c", MOD_PAT, MOD_OPT, PCRE2_NEVER_BACKSLASH_C, PO(options) },+ { "never_ucp", MOD_PAT, MOD_OPT, PCRE2_NEVER_UCP, PO(options) },+ { "never_utf", MOD_PAT, MOD_OPT, PCRE2_NEVER_UTF, PO(options) },+ { "newline", MOD_CTC, MOD_NL, 0, CO(newline_convention) },+ { "no_auto_capture", MOD_PAT, MOD_OPT, PCRE2_NO_AUTO_CAPTURE, PO(options) },+ { "no_auto_possess", MOD_PATP, MOD_OPT, PCRE2_NO_AUTO_POSSESS, PO(options) },+ { "no_dotstar_anchor", MOD_PAT, MOD_OPT, PCRE2_NO_DOTSTAR_ANCHOR, PO(options) },+ { "no_jit", MOD_DAT, MOD_OPT, PCRE2_NO_JIT, DO(options) },+ { "no_start_optimize", MOD_PATP, MOD_OPT, PCRE2_NO_START_OPTIMIZE, PO(options) },+ { "no_utf_check", MOD_PD, MOD_OPT, PCRE2_NO_UTF_CHECK, PD(options) },+ { "notbol", MOD_DAT, MOD_OPT, PCRE2_NOTBOL, DO(options) },+ { "notempty", MOD_DAT, MOD_OPT, PCRE2_NOTEMPTY, DO(options) },+ { "notempty_atstart", MOD_DAT, MOD_OPT, PCRE2_NOTEMPTY_ATSTART, DO(options) },+ { "noteol", MOD_DAT, MOD_OPT, PCRE2_NOTEOL, DO(options) },+ { "null_context", MOD_PD, MOD_CTL, CTL_NULLCONTEXT, PO(control) },+ { "offset", MOD_DAT, MOD_INT, 0, DO(offset) },+ { "offset_limit", MOD_CTM, MOD_SIZ, 0, MO(offset_limit)},+ { "ovector", MOD_DAT, MOD_INT, 0, DO(oveccount) },+ { "parens_nest_limit", MOD_CTC, MOD_INT, 0, CO(parens_nest_limit) },+ { "partial_hard", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_HARD, DO(options) },+ { "partial_soft", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_SOFT, DO(options) },+ { "ph", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_HARD, DO(options) },+ { "posix", MOD_PAT, MOD_CTL, CTL_POSIX, PO(control) },+ { "posix_nosub", MOD_PAT, MOD_CTL, CTL_POSIX|CTL_POSIX_NOSUB, PO(control) },+ { "posix_startend", MOD_DAT, MOD_IN2, 0, DO(startend) },+ { "ps", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_SOFT, DO(options) },+ { "push", MOD_PAT, MOD_CTL, CTL_PUSH, PO(control) },+ { "pushcopy", MOD_PAT, MOD_CTL, CTL_PUSHCOPY, PO(control) },+ { "pushtablescopy", MOD_PAT, MOD_CTL, CTL_PUSHTABLESCOPY, PO(control) },+ { "recursion_limit", MOD_CTM, MOD_INT, 0, MO(depth_limit) }, /* Obsolete synonym */+ { "regerror_buffsize", MOD_PAT, MOD_INT, 0, PO(regerror_buffsize) },+ { "replace", MOD_PND, MOD_STR, REPLACE_MODSIZE, PO(replacement) },+ { "stackguard", MOD_PAT, MOD_INT, 0, PO(stackguard_test) },+ { "startchar", MOD_PND, MOD_CTL, CTL_STARTCHAR, PO(control) },+ { "startoffset", MOD_DAT, MOD_INT, 0, DO(offset) },+ { "subject_literal", MOD_PATP, MOD_CTL, CTL2_SUBJECT_LITERAL, PO(control2) },+ { "substitute_callout", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_CALLOUT, PO(control2) },+ { "substitute_extended", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_EXTENDED, PO(control2) },+ { "substitute_literal", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_LITERAL, PO(control2) },+ { "substitute_matched", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_MATCHED, PO(control2) },+ { "substitute_overflow_length", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_OVERFLOW_LENGTH, PO(control2) },+ { "substitute_replacement_only", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_REPLACEMENT_ONLY, PO(control2) },+ { "substitute_skip", MOD_PND, MOD_INT, 0, PO(substitute_skip) },+ { "substitute_stop", MOD_PND, MOD_INT, 0, PO(substitute_stop) },+ { "substitute_unknown_unset", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_UNKNOWN_UNSET, PO(control2) },+ { "substitute_unset_empty", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_UNSET_EMPTY, PO(control2) },+ { "tables", MOD_PAT, MOD_INT, 0, PO(tables_id) },+ { "ucp", MOD_PATP, MOD_OPT, PCRE2_UCP, PO(options) },+ { "ungreedy", MOD_PAT, MOD_OPT, PCRE2_UNGREEDY, PO(options) },+ { "use_length", MOD_PAT, MOD_CTL, CTL_USE_LENGTH, PO(control) },+ { "use_offset_limit", MOD_PAT, MOD_OPT, PCRE2_USE_OFFSET_LIMIT, PO(options) },+ { "utf", MOD_PATP, MOD_OPT, PCRE2_UTF, PO(options) },+ { "utf8_input", MOD_PAT, MOD_CTL, CTL_UTF8_INPUT, PO(control) },+ { "zero_terminate", MOD_DAT, MOD_CTL, CTL_ZERO_TERMINATE, DO(control) }+};++#define MODLISTCOUNT sizeof(modlist)/sizeof(modstruct)++/* Controls and options that are supported for use with the POSIX interface. */++#define POSIX_SUPPORTED_COMPILE_OPTIONS ( \+ PCRE2_CASELESS|PCRE2_DOTALL|PCRE2_LITERAL|PCRE2_MULTILINE|PCRE2_UCP| \+ PCRE2_UTF|PCRE2_UNGREEDY)++#define POSIX_SUPPORTED_COMPILE_EXTRA_OPTIONS (0)++#define POSIX_SUPPORTED_COMPILE_CONTROLS ( \+ CTL_AFTERTEXT|CTL_ALLAFTERTEXT|CTL_EXPAND|CTL_HEXPAT|CTL_POSIX| \+ CTL_POSIX_NOSUB|CTL_USE_LENGTH)++#define POSIX_SUPPORTED_COMPILE_CONTROLS2 (0)++#define POSIX_SUPPORTED_MATCH_OPTIONS ( \+ PCRE2_NOTBOL|PCRE2_NOTEMPTY|PCRE2_NOTEOL)++#define POSIX_SUPPORTED_MATCH_CONTROLS (CTL_AFTERTEXT|CTL_ALLAFTERTEXT)+#define POSIX_SUPPORTED_MATCH_CONTROLS2 (0)++/* Control bits that are not ignored with 'push'. */++#define PUSH_SUPPORTED_COMPILE_CONTROLS ( \+ CTL_BINCODE|CTL_CALLOUT_INFO|CTL_FULLBINCODE|CTL_HEXPAT|CTL_INFO| \+ CTL_JITVERIFY|CTL_MEMORY|CTL_FRAMESIZE|CTL_PUSH|CTL_PUSHCOPY| \+ CTL_PUSHTABLESCOPY|CTL_USE_LENGTH)++#define PUSH_SUPPORTED_COMPILE_CONTROLS2 (CTL2_BSR_SET|CTL2_NL_SET)++/* Controls that apply only at compile time with 'push'. */++#define PUSH_COMPILE_ONLY_CONTROLS CTL_JITVERIFY+#define PUSH_COMPILE_ONLY_CONTROLS2 (0)++/* Controls that are forbidden with #pop or #popcopy. */++#define NOTPOP_CONTROLS (CTL_HEXPAT|CTL_POSIX|CTL_POSIX_NOSUB|CTL_PUSH| \+ CTL_PUSHCOPY|CTL_PUSHTABLESCOPY|CTL_USE_LENGTH)++/* Pattern controls that are mutually exclusive. At present these are all in+the first control word. Note that CTL_POSIX_NOSUB is always accompanied by+CTL_POSIX, so it doesn't need its own entries. */++static uint32_t exclusive_pat_controls[] = {+ CTL_POSIX | CTL_PUSH,+ CTL_POSIX | CTL_PUSHCOPY,+ CTL_POSIX | CTL_PUSHTABLESCOPY,+ CTL_PUSH | CTL_PUSHCOPY,+ CTL_PUSH | CTL_PUSHTABLESCOPY,+ CTL_PUSHCOPY | CTL_PUSHTABLESCOPY,+ CTL_EXPAND | CTL_HEXPAT };++/* Data controls that are mutually exclusive. At present these are all in the+first control word. */++static uint32_t exclusive_dat_controls[] = {+ CTL_ALLUSEDTEXT | CTL_STARTCHAR,+ CTL_FINDLIMITS | CTL_NULLCONTEXT };++/* Table of single-character abbreviated modifiers. The index field is+initialized to -1, but the first time the modifier is encountered, it is filled+in with the index of the full entry in modlist, to save repeated searching when+processing multiple test items. This short list is searched serially, so its+order does not matter. */++typedef struct c1modstruct {+ const char *fullname;+ uint32_t onechar;+ int index;+} c1modstruct;++static c1modstruct c1modlist[] = {+ { "bincode", 'B', -1 },+ { "info", 'I', -1 },+ { "global", 'g', -1 },+ { "caseless", 'i', -1 },+ { "multiline", 'm', -1 },+ { "no_auto_capture", 'n', -1 },+ { "dotall", 's', -1 },+ { "extended", 'x', -1 }+};++#define C1MODLISTCOUNT sizeof(c1modlist)/sizeof(c1modstruct)++/* Table of arguments for the -C command line option. Use macros to make the+table itself easier to read. */++#if defined SUPPORT_PCRE2_8+#define SUPPORT_8 1+#endif+#if defined SUPPORT_PCRE2_16+#define SUPPORT_16 1+#endif+#if defined SUPPORT_PCRE2_32+#define SUPPORT_32 1+#endif++#ifndef SUPPORT_8+#define SUPPORT_8 0+#endif+#ifndef SUPPORT_16+#define SUPPORT_16 0+#endif+#ifndef SUPPORT_32+#define SUPPORT_32 0+#endif++#ifdef EBCDIC+#define SUPPORT_EBCDIC 1+#define EBCDIC_NL CHAR_LF+#else+#define SUPPORT_EBCDIC 0+#define EBCDIC_NL 0+#endif++#ifdef NEVER_BACKSLASH_C+#define BACKSLASH_C 0+#else+#define BACKSLASH_C 1+#endif++typedef struct coptstruct {+ const char *name;+ uint32_t type;+ uint32_t value;+} coptstruct;++enum { CONF_BSR,+ CONF_FIX,+ CONF_FIZ,+ CONF_INT,+ CONF_NL+};++static coptstruct coptlist[] = {+ { "backslash-C", CONF_FIX, BACKSLASH_C },+ { "bsr", CONF_BSR, PCRE2_CONFIG_BSR },+ { "ebcdic", CONF_FIX, SUPPORT_EBCDIC },+ { "ebcdic-nl", CONF_FIZ, EBCDIC_NL },+ { "jit", CONF_INT, PCRE2_CONFIG_JIT },+ { "linksize", CONF_INT, PCRE2_CONFIG_LINKSIZE },+ { "newline", CONF_NL, PCRE2_CONFIG_NEWLINE },+ { "pcre2-16", CONF_FIX, SUPPORT_16 },+ { "pcre2-32", CONF_FIX, SUPPORT_32 },+ { "pcre2-8", CONF_FIX, SUPPORT_8 },+ { "unicode", CONF_INT, PCRE2_CONFIG_UNICODE }+};++#define COPTLISTCOUNT sizeof(coptlist)/sizeof(coptstruct)++#undef SUPPORT_8+#undef SUPPORT_16+#undef SUPPORT_32+#undef SUPPORT_EBCDIC+++/* ----------------------- Static variables ------------------------ */++static FILE *infile;+static FILE *outfile;++static const void *last_callout_mark;+static PCRE2_JIT_STACK *jit_stack = NULL;+static size_t jit_stack_size = 0;++static BOOL first_callout;+static BOOL jit_was_used;+static BOOL restrict_for_perl_test = FALSE;+static BOOL show_memory = FALSE;++static int code_unit_size; /* Bytes */+static int jitrc; /* Return from JIT compile */+static int test_mode = DEFAULT_TEST_MODE;+static int timeit = 0;+static int timeitm = 0;++clock_t total_compile_time = 0;+clock_t total_jit_compile_time = 0;+clock_t total_match_time = 0;++static uint32_t dfa_matched;+static uint32_t forbid_utf = 0;+static uint32_t maxlookbehind;+static uint32_t max_oveccount;+static uint32_t callout_count;+static uint32_t maxcapcount;++static uint16_t local_newline_default = 0;++static VERSION_TYPE jittarget[VERSION_SIZE];+static VERSION_TYPE version[VERSION_SIZE];+static VERSION_TYPE uversion[VERSION_SIZE];++static patctl def_patctl;+static patctl pat_patctl;+static datctl def_datctl;+static datctl dat_datctl;++static void *patstack[PATSTACKSIZE];+static int patstacknext = 0;++static void *malloclist[MALLOCLISTSIZE];+static PCRE2_SIZE malloclistlength[MALLOCLISTSIZE];+static uint32_t malloclistptr = 0;++#ifdef SUPPORT_PCRE2_8+static regex_t preg = { NULL, NULL, 0, 0, 0, 0 };+#endif++static int *dfa_workspace = NULL;+static const uint8_t *locale_tables = NULL;+static const uint8_t *use_tables = NULL;+static uint8_t locale_name[32];+static uint8_t *tables3 = NULL; /* For binary-loaded tables */+static uint32_t loadtables_length = 0;++/* We need buffers for building 16/32-bit strings; 8-bit strings don't need+rebuilding, but set up the same naming scheme for use in macros. The "buffer"+buffer is where all input lines are read. Its size is the same as pbuffer8.+Pattern lines are always copied to pbuffer8 for use in callouts, even if they+are actually compiled from pbuffer16 or pbuffer32. */++static size_t pbuffer8_size = 50000; /* Initial size, bytes */+static uint8_t *pbuffer8 = NULL;+static uint8_t *buffer = NULL;++/* The dbuffer is where all processed data lines are put. In non-8-bit modes it+is cast as needed. For long data lines it grows as necessary. */++static size_t dbuffer_size = 1u << 14; /* Initial size, bytes */+static uint8_t *dbuffer = NULL;+++/* ---------------- Mode-dependent variables -------------------*/++#ifdef SUPPORT_PCRE2_8+static pcre2_code_8 *compiled_code8;+static pcre2_general_context_8 *general_context8, *general_context_copy8;+static pcre2_compile_context_8 *pat_context8, *default_pat_context8;+static pcre2_convert_context_8 *con_context8, *default_con_context8;+static pcre2_match_context_8 *dat_context8, *default_dat_context8;+static pcre2_match_data_8 *match_data8;+#endif++#ifdef SUPPORT_PCRE2_16+static pcre2_code_16 *compiled_code16;+static pcre2_general_context_16 *general_context16, *general_context_copy16;+static pcre2_compile_context_16 *pat_context16, *default_pat_context16;+static pcre2_convert_context_16 *con_context16, *default_con_context16;+static pcre2_match_context_16 *dat_context16, *default_dat_context16;+static pcre2_match_data_16 *match_data16;+static PCRE2_SIZE pbuffer16_size = 0; /* Set only when needed */+static uint16_t *pbuffer16 = NULL;+#endif++#ifdef SUPPORT_PCRE2_32+static pcre2_code_32 *compiled_code32;+static pcre2_general_context_32 *general_context32, *general_context_copy32;+static pcre2_compile_context_32 *pat_context32, *default_pat_context32;+static pcre2_convert_context_32 *con_context32, *default_con_context32;+static pcre2_match_context_32 *dat_context32, *default_dat_context32;+static pcre2_match_data_32 *match_data32;+static PCRE2_SIZE pbuffer32_size = 0; /* Set only when needed */+static uint32_t *pbuffer32 = NULL;+#endif+++/* ---------------- Macros that work in all modes ----------------- */++#define CAST8VAR(x) CASTVAR(uint8_t *, x)+#define SET(x,y) SETOP(x,y,=)+#define SETPLUS(x,y) SETOP(x,y,+=)+#define strlen8(x) strlen((char *)x)+++/* ---------------- Mode-dependent, runtime-testing macros ------------------*/++/* Define macros for variables and functions that must be selected dynamically+depending on the mode setting (8, 16, 32). These are dependent on which modes+are supported. */++#if (defined (SUPPORT_PCRE2_8) + defined (SUPPORT_PCRE2_16) + \+ defined (SUPPORT_PCRE2_32)) >= 2++/* ----- All three modes supported ----- */++#if defined(SUPPORT_PCRE2_8) && defined(SUPPORT_PCRE2_16) && defined(SUPPORT_PCRE2_32)++#define CASTFLD(t,a,b) ((test_mode == PCRE8_MODE)? (t)(G(a,8)->b) : \+ (test_mode == PCRE16_MODE)? (t)(G(a,16)->b) : (t)(G(a,32)->b))++#define CASTVAR(t,x) ( \+ (test_mode == PCRE8_MODE)? (t)G(x,8) : \+ (test_mode == PCRE16_MODE)? (t)G(x,16) : (t)G(x,32))++#define CODE_UNIT(a,b) ( \+ (test_mode == PCRE8_MODE)? (uint32_t)(((PCRE2_SPTR8)(a))[b]) : \+ (test_mode == PCRE16_MODE)? (uint32_t)(((PCRE2_SPTR16)(a))[b]) : \+ (uint32_t)(((PCRE2_SPTR32)(a))[b]))++#define CONCTXCPY(a,b) \+ if (test_mode == PCRE8_MODE) \+ memcpy(G(a,8),G(b,8),sizeof(pcre2_convert_context_8)); \+ else if (test_mode == PCRE16_MODE) \+ memcpy(G(a,16),G(b,16),sizeof(pcre2_convert_context_16)); \+ else memcpy(G(a,32),G(b,32),sizeof(pcre2_convert_context_32))++#define CONVERT_COPY(a,b,c) \+ if (test_mode == PCRE8_MODE) \+ memcpy(G(a,8),(char *)b,c); \+ else if (test_mode == PCRE16_MODE) \+ memcpy(G(a,16),(char *)b,(c)*2); \+ else if (test_mode == PCRE32_MODE) \+ memcpy(G(a,32),(char *)b,(c)*4)++#define DATCTXCPY(a,b) \+ if (test_mode == PCRE8_MODE) \+ memcpy(G(a,8),G(b,8),sizeof(pcre2_match_context_8)); \+ else if (test_mode == PCRE16_MODE) \+ memcpy(G(a,16),G(b,16),sizeof(pcre2_match_context_16)); \+ else memcpy(G(a,32),G(b,32),sizeof(pcre2_match_context_32))++#define FLD(a,b) ((test_mode == PCRE8_MODE)? G(a,8)->b : \+ (test_mode == PCRE16_MODE)? G(a,16)->b : G(a,32)->b)++#define PATCTXCPY(a,b) \+ if (test_mode == PCRE8_MODE) \+ memcpy(G(a,8),G(b,8),sizeof(pcre2_compile_context_8)); \+ else if (test_mode == PCRE16_MODE) \+ memcpy(G(a,16),G(b,16),sizeof(pcre2_compile_context_16)); \+ else memcpy(G(a,32),G(b,32),sizeof(pcre2_compile_context_32))++#define PCHARS(lv, p, offset, len, utf, f) \+ if (test_mode == PCRE32_MODE) \+ lv = pchars32((PCRE2_SPTR32)(p)+offset, len, utf, f); \+ else if (test_mode == PCRE16_MODE) \+ lv = pchars16((PCRE2_SPTR16)(p)+offset, len, utf, f); \+ else \+ lv = pchars8((PCRE2_SPTR8)(p)+offset, len, utf, f)++#define PCHARSV(p, offset, len, utf, f) \+ if (test_mode == PCRE32_MODE) \+ (void)pchars32((PCRE2_SPTR32)(p)+offset, len, utf, f); \+ else if (test_mode == PCRE16_MODE) \+ (void)pchars16((PCRE2_SPTR16)(p)+offset, len, utf, f); \+ else \+ (void)pchars8((PCRE2_SPTR8)(p)+offset, len, utf, f)++#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_callout_enumerate_8(compiled_code8, \+ (int (*)(struct pcre2_callout_enumerate_block_8 *, void *))b,c); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_callout_enumerate_16(compiled_code16, \+ (int(*)(struct pcre2_callout_enumerate_block_16 *, void *))b,c); \+ else \+ a = pcre2_callout_enumerate_32(compiled_code32, \+ (int (*)(struct pcre2_callout_enumerate_block_32 *, void *))b,c)++#define PCRE2_CODE_COPY_FROM_VOID(a,b) \+ if (test_mode == PCRE8_MODE) \+ G(a,8) = pcre2_code_copy_8(b); \+ else if (test_mode == PCRE16_MODE) \+ G(a,16) = pcre2_code_copy_16(b); \+ else \+ G(a,32) = pcre2_code_copy_32(b)++#define PCRE2_CODE_COPY_TO_VOID(a,b) \+ if (test_mode == PCRE8_MODE) \+ a = (void *)pcre2_code_copy_8(G(b,8)); \+ else if (test_mode == PCRE16_MODE) \+ a = (void *)pcre2_code_copy_16(G(b,16)); \+ else \+ a = (void *)pcre2_code_copy_32(G(b,32))++#define PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(a,b) \+ if (test_mode == PCRE8_MODE) \+ a = (void *)pcre2_code_copy_with_tables_8(G(b,8)); \+ else if (test_mode == PCRE16_MODE) \+ a = (void *)pcre2_code_copy_with_tables_16(G(b,16)); \+ else \+ a = (void *)pcre2_code_copy_with_tables_32(G(b,32))++#define PCRE2_COMPILE(a,b,c,d,e,f,g) \+ if (test_mode == PCRE8_MODE) \+ G(a,8) = pcre2_compile_8(G(b,8),c,d,e,f,g); \+ else if (test_mode == PCRE16_MODE) \+ G(a,16) = pcre2_compile_16(G(b,16),c,d,e,f,g); \+ else \+ G(a,32) = pcre2_compile_32(G(b,32),c,d,e,f,g)++#define PCRE2_CONVERTED_PATTERN_FREE(a) \+ if (test_mode == PCRE8_MODE) pcre2_converted_pattern_free_8((PCRE2_UCHAR8 *)a); \+ else if (test_mode == PCRE16_MODE) pcre2_converted_pattern_free_16((PCRE2_UCHAR16 *)a); \+ else pcre2_converted_pattern_free_32((PCRE2_UCHAR32 *)a)++#define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_dfa_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h,i,j); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_dfa_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h,i,j); \+ else \+ a = pcre2_dfa_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h,i,j)++#define PCRE2_GET_ERROR_MESSAGE(r,a,b) \+ if (test_mode == PCRE8_MODE) \+ r = pcre2_get_error_message_8(a,G(b,8),G(G(b,8),_size)); \+ else if (test_mode == PCRE16_MODE) \+ r = pcre2_get_error_message_16(a,G(b,16),G(G(b,16),_size/2)); \+ else \+ r = pcre2_get_error_message_32(a,G(b,32),G(G(b,32),_size/4))++#define PCRE2_GET_OVECTOR_COUNT(a,b) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_get_ovector_count_8(G(b,8)); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_get_ovector_count_16(G(b,16)); \+ else \+ a = pcre2_get_ovector_count_32(G(b,32))++#define PCRE2_GET_STARTCHAR(a,b) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_get_startchar_8(G(b,8)); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_get_startchar_16(G(b,16)); \+ else \+ a = pcre2_get_startchar_32(G(b,32))++#define PCRE2_JIT_COMPILE(r,a,b) \+ if (test_mode == PCRE8_MODE) r = pcre2_jit_compile_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) r = pcre2_jit_compile_16(G(a,16),b); \+ else r = pcre2_jit_compile_32(G(a,32),b)++#define PCRE2_JIT_FREE_UNUSED_MEMORY(a) \+ if (test_mode == PCRE8_MODE) pcre2_jit_free_unused_memory_8(G(a,8)); \+ else if (test_mode == PCRE16_MODE) pcre2_jit_free_unused_memory_16(G(a,16)); \+ else pcre2_jit_free_unused_memory_32(G(a,32))++#define PCRE2_JIT_MATCH(a,b,c,d,e,f,g,h) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_jit_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_jit_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h); \+ else \+ a = pcre2_jit_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h)++#define PCRE2_JIT_STACK_CREATE(a,b,c,d) \+ if (test_mode == PCRE8_MODE) \+ a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_8(b,c,d); \+ else if (test_mode == PCRE16_MODE) \+ a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_16(b,c,d); \+ else \+ a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_32(b,c,d);++#define PCRE2_JIT_STACK_ASSIGN(a,b,c) \+ if (test_mode == PCRE8_MODE) \+ pcre2_jit_stack_assign_8(G(a,8),(pcre2_jit_callback_8)b,c); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_jit_stack_assign_16(G(a,16),(pcre2_jit_callback_16)b,c); \+ else \+ pcre2_jit_stack_assign_32(G(a,32),(pcre2_jit_callback_32)b,c);++#define PCRE2_JIT_STACK_FREE(a) \+ if (test_mode == PCRE8_MODE) \+ pcre2_jit_stack_free_8((pcre2_jit_stack_8 *)a); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_jit_stack_free_16((pcre2_jit_stack_16 *)a); \+ else \+ pcre2_jit_stack_free_32((pcre2_jit_stack_32 *)a);++#define PCRE2_MAKETABLES(a) \+ if (test_mode == PCRE8_MODE) a = pcre2_maketables_8(NULL); \+ else if (test_mode == PCRE16_MODE) a = pcre2_maketables_16(NULL); \+ else a = pcre2_maketables_32(NULL)++#define PCRE2_MATCH(a,b,c,d,e,f,g,h) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h); \+ else \+ a = pcre2_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h)++#define PCRE2_MATCH_DATA_CREATE(a,b,c) \+ if (test_mode == PCRE8_MODE) \+ G(a,8) = pcre2_match_data_create_8(b,c); \+ else if (test_mode == PCRE16_MODE) \+ G(a,16) = pcre2_match_data_create_16(b,c); \+ else \+ G(a,32) = pcre2_match_data_create_32(b,c)++#define PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(a,b,c) \+ if (test_mode == PCRE8_MODE) \+ G(a,8) = pcre2_match_data_create_from_pattern_8(G(b,8),c); \+ else if (test_mode == PCRE16_MODE) \+ G(a,16) = pcre2_match_data_create_from_pattern_16(G(b,16),c); \+ else \+ G(a,32) = pcre2_match_data_create_from_pattern_32(G(b,32),c)++#define PCRE2_MATCH_DATA_FREE(a) \+ if (test_mode == PCRE8_MODE) \+ pcre2_match_data_free_8(G(a,8)); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_match_data_free_16(G(a,16)); \+ else \+ pcre2_match_data_free_32(G(a,32))++#define PCRE2_PATTERN_CONVERT(a,b,c,d,e,f,g) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_pattern_convert_8(G(b,8),c,d,(PCRE2_UCHAR8 **)e,f,G(g,8)); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_pattern_convert_16(G(b,16),c,d,(PCRE2_UCHAR16 **)e,f,G(g,16)); \+ else \+ a = pcre2_pattern_convert_32(G(b,32),c,d,(PCRE2_UCHAR32 **)e,f,G(g,32))++#define PCRE2_PATTERN_INFO(a,b,c,d) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_pattern_info_8(G(b,8),c,d); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_pattern_info_16(G(b,16),c,d); \+ else \+ a = pcre2_pattern_info_32(G(b,32),c,d)++#define PCRE2_PRINTINT(a) \+ if (test_mode == PCRE8_MODE) \+ pcre2_printint_8(compiled_code8,outfile,a); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_printint_16(compiled_code16,outfile,a); \+ else \+ pcre2_printint_32(compiled_code32,outfile,a)++#define PCRE2_SERIALIZE_DECODE(r,a,b,c,d) \+ if (test_mode == PCRE8_MODE) \+ r = pcre2_serialize_decode_8((pcre2_code_8 **)a,b,c,G(d,8)); \+ else if (test_mode == PCRE16_MODE) \+ r = pcre2_serialize_decode_16((pcre2_code_16 **)a,b,c,G(d,16)); \+ else \+ r = pcre2_serialize_decode_32((pcre2_code_32 **)a,b,c,G(d,32))++#define PCRE2_SERIALIZE_ENCODE(r,a,b,c,d,e) \+ if (test_mode == PCRE8_MODE) \+ r = pcre2_serialize_encode_8((const pcre2_code_8 **)a,b,c,d,G(e,8)); \+ else if (test_mode == PCRE16_MODE) \+ r = pcre2_serialize_encode_16((const pcre2_code_16 **)a,b,c,d,G(e,16)); \+ else \+ r = pcre2_serialize_encode_32((const pcre2_code_32 **)a,b,c,d,G(e,32))++#define PCRE2_SERIALIZE_FREE(a) \+ if (test_mode == PCRE8_MODE) \+ pcre2_serialize_free_8(a); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_serialize_free_16(a); \+ else \+ pcre2_serialize_free_32(a)++#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \+ if (test_mode == PCRE8_MODE) \+ r = pcre2_serialize_get_number_of_codes_8(a); \+ else if (test_mode == PCRE16_MODE) \+ r = pcre2_serialize_get_number_of_codes_16(a); \+ else \+ r = pcre2_serialize_get_number_of_codes_32(a); \++#define PCRE2_SET_CALLOUT(a,b,c) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_callout_8(G(a,8),(int (*)(pcre2_callout_block_8 *, void *))b,c); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_callout_16(G(a,16),(int (*)(pcre2_callout_block_16 *, void *))b,c); \+ else \+ pcre2_set_callout_32(G(a,32),(int (*)(pcre2_callout_block_32 *, void *))b,c);++#define PCRE2_SET_CHARACTER_TABLES(a,b) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_character_tables_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_character_tables_16(G(a,16),b); \+ else \+ pcre2_set_character_tables_32(G(a,32),b)++#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_compile_recursion_guard_8(G(a,8),b,c); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_compile_recursion_guard_16(G(a,16),b,c); \+ else \+ pcre2_set_compile_recursion_guard_32(G(a,32),b,c)++#define PCRE2_SET_DEPTH_LIMIT(a,b) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_depth_limit_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_depth_limit_16(G(a,16),b); \+ else \+ pcre2_set_depth_limit_32(G(a,32),b)++#define PCRE2_SET_GLOB_SEPARATOR(r,a,b) \+ if (test_mode == PCRE8_MODE) \+ r = pcre2_set_glob_separator_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ r = pcre2_set_glob_separator_16(G(a,16),b); \+ else \+ r = pcre2_set_glob_separator_32(G(a,32),b)++#define PCRE2_SET_GLOB_ESCAPE(r,a,b) \+ if (test_mode == PCRE8_MODE) \+ r = pcre2_set_glob_escape_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ r = pcre2_set_glob_escape_16(G(a,16),b); \+ else \+ r = pcre2_set_glob_escape_32(G(a,32),b)++#define PCRE2_SET_HEAP_LIMIT(a,b) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_heap_limit_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_heap_limit_16(G(a,16),b); \+ else \+ pcre2_set_heap_limit_32(G(a,32),b)++#define PCRE2_SET_MATCH_LIMIT(a,b) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_match_limit_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_match_limit_16(G(a,16),b); \+ else \+ pcre2_set_match_limit_32(G(a,32),b)++#define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_max_pattern_length_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_max_pattern_length_16(G(a,16),b); \+ else \+ pcre2_set_max_pattern_length_32(G(a,32),b)++#define PCRE2_SET_OFFSET_LIMIT(a,b) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_offset_limit_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_offset_limit_16(G(a,16),b); \+ else \+ pcre2_set_offset_limit_32(G(a,32),b)++#define PCRE2_SET_PARENS_NEST_LIMIT(a,b) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_parens_nest_limit_8(G(a,8),b); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_parens_nest_limit_16(G(a,16),b); \+ else \+ pcre2_set_parens_nest_limit_32(G(a,32),b)++#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \+ if (test_mode == PCRE8_MODE) \+ pcre2_set_substitute_callout_8(G(a,8), \+ (int (*)(pcre2_substitute_callout_block_8 *, void *))b,c); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_set_substitute_callout_16(G(a,16), \+ (int (*)(pcre2_substitute_callout_block_16 *, void *))b,c); \+ else \+ pcre2_set_substitute_callout_32(G(a,32), \+ (int (*)(pcre2_substitute_callout_block_32 *, void *))b,c)++#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h, \+ (PCRE2_SPTR8)i,j,(PCRE2_UCHAR8 *)k,l); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h, \+ (PCRE2_SPTR16)i,j,(PCRE2_UCHAR16 *)k,l); \+ else \+ a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h, \+ (PCRE2_SPTR32)i,j,(PCRE2_UCHAR32 *)k,l)++#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_substring_copy_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 *)d,e); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_substring_copy_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 *)d,e); \+ else \+ a = pcre2_substring_copy_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 *)d,e)++#define PCRE2_SUBSTRING_COPY_BYNUMBER(a,b,c,d,e) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_substring_copy_bynumber_8(G(b,8),c,(PCRE2_UCHAR8 *)d,e); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_substring_copy_bynumber_16(G(b,16),c,(PCRE2_UCHAR16 *)d,e); \+ else \+ a = pcre2_substring_copy_bynumber_32(G(b,32),c,(PCRE2_UCHAR32 *)d,e)++#define PCRE2_SUBSTRING_FREE(a) \+ if (test_mode == PCRE8_MODE) pcre2_substring_free_8((PCRE2_UCHAR8 *)a); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_substring_free_16((PCRE2_UCHAR16 *)a); \+ else pcre2_substring_free_32((PCRE2_UCHAR32 *)a)++#define PCRE2_SUBSTRING_GET_BYNAME(a,b,c,d,e) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_substring_get_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 **)d,e); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_substring_get_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 **)d,e); \+ else \+ a = pcre2_substring_get_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 **)d,e)++#define PCRE2_SUBSTRING_GET_BYNUMBER(a,b,c,d,e) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_substring_get_bynumber_8(G(b,8),c,(PCRE2_UCHAR8 **)d,e); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_substring_get_bynumber_16(G(b,16),c,(PCRE2_UCHAR16 **)d,e); \+ else \+ a = pcre2_substring_get_bynumber_32(G(b,32),c,(PCRE2_UCHAR32 **)d,e)++#define PCRE2_SUBSTRING_LENGTH_BYNAME(a,b,c,d) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_substring_length_byname_8(G(b,8),G(c,8),d); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_substring_length_byname_16(G(b,16),G(c,16),d); \+ else \+ a = pcre2_substring_length_byname_32(G(b,32),G(c,32),d)++#define PCRE2_SUBSTRING_LENGTH_BYNUMBER(a,b,c,d) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_substring_length_bynumber_8(G(b,8),c,d); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_substring_length_bynumber_16(G(b,16),c,d); \+ else \+ a = pcre2_substring_length_bynumber_32(G(b,32),c,d)++#define PCRE2_SUBSTRING_LIST_GET(a,b,c,d) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_substring_list_get_8(G(b,8),(PCRE2_UCHAR8 ***)c,d); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_substring_list_get_16(G(b,16),(PCRE2_UCHAR16 ***)c,d); \+ else \+ a = pcre2_substring_list_get_32(G(b,32),(PCRE2_UCHAR32 ***)c,d)++#define PCRE2_SUBSTRING_LIST_FREE(a) \+ if (test_mode == PCRE8_MODE) \+ pcre2_substring_list_free_8((PCRE2_SPTR8 *)a); \+ else if (test_mode == PCRE16_MODE) \+ pcre2_substring_list_free_16((PCRE2_SPTR16 *)a); \+ else \+ pcre2_substring_list_free_32((PCRE2_SPTR32 *)a)++#define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \+ if (test_mode == PCRE8_MODE) \+ a = pcre2_substring_number_from_name_8(G(b,8),G(c,8)); \+ else if (test_mode == PCRE16_MODE) \+ a = pcre2_substring_number_from_name_16(G(b,16),G(c,16)); \+ else \+ a = pcre2_substring_number_from_name_32(G(b,32),G(c,32))++#define PTR(x) ( \+ (test_mode == PCRE8_MODE)? (void *)G(x,8) : \+ (test_mode == PCRE16_MODE)? (void *)G(x,16) : \+ (void *)G(x,32))++#define SETFLD(x,y,z) \+ if (test_mode == PCRE8_MODE) G(x,8)->y = z; \+ else if (test_mode == PCRE16_MODE) G(x,16)->y = z; \+ else G(x,32)->y = z++#define SETFLDVEC(x,y,v,z) \+ if (test_mode == PCRE8_MODE) G(x,8)->y[v] = z; \+ else if (test_mode == PCRE16_MODE) G(x,16)->y[v] = z; \+ else G(x,32)->y[v] = z++#define SETOP(x,y,z) \+ if (test_mode == PCRE8_MODE) G(x,8) z y; \+ else if (test_mode == PCRE16_MODE) G(x,16) z y; \+ else G(x,32) z y++#define SETCASTPTR(x,y) \+ if (test_mode == PCRE8_MODE) \+ G(x,8) = (uint8_t *)(y); \+ else if (test_mode == PCRE16_MODE) \+ G(x,16) = (uint16_t *)(y); \+ else \+ G(x,32) = (uint32_t *)(y)++#define STRLEN(p) ((test_mode == PCRE8_MODE)? ((int)strlen((char *)p)) : \+ (test_mode == PCRE16_MODE)? ((int)strlen16((PCRE2_SPTR16)p)) : \+ ((int)strlen32((PCRE2_SPTR32)p)))++#define SUB1(a,b) \+ if (test_mode == PCRE8_MODE) G(a,8)(G(b,8)); \+ else if (test_mode == PCRE16_MODE) G(a,16)(G(b,16)); \+ else G(a,32)(G(b,32))++#define SUB2(a,b,c) \+ if (test_mode == PCRE8_MODE) G(a,8)(G(b,8),G(c,8)); \+ else if (test_mode == PCRE16_MODE) G(a,16)(G(b,16),G(c,16)); \+ else G(a,32)(G(b,32),G(c,32))++#define TEST(x,r,y) ( \+ (test_mode == PCRE8_MODE && G(x,8) r (y)) || \+ (test_mode == PCRE16_MODE && G(x,16) r (y)) || \+ (test_mode == PCRE32_MODE && G(x,32) r (y)))++#define TESTFLD(x,f,r,y) ( \+ (test_mode == PCRE8_MODE && G(x,8)->f r (y)) || \+ (test_mode == PCRE16_MODE && G(x,16)->f r (y)) || \+ (test_mode == PCRE32_MODE && G(x,32)->f r (y)))+++/* ----- Two out of three modes are supported ----- */++#else++/* We can use some macro trickery to make a single set of definitions work in+the three different cases. */++/* ----- 32-bit and 16-bit but not 8-bit supported ----- */++#if defined(SUPPORT_PCRE2_32) && defined(SUPPORT_PCRE2_16)+#define BITONE 32+#define BITTWO 16++/* ----- 32-bit and 8-bit but not 16-bit supported ----- */++#elif defined(SUPPORT_PCRE2_32) && defined(SUPPORT_PCRE2_8)+#define BITONE 32+#define BITTWO 8++/* ----- 16-bit and 8-bit but not 32-bit supported ----- */++#else+#define BITONE 16+#define BITTWO 8+#endif+++/* ----- Common macros for two-mode cases ----- */++#define BYTEONE (BITONE/8)+#define BYTETWO (BITTWO/8)++#define CASTFLD(t,a,b) \+ ((test_mode == G(G(PCRE,BITONE),_MODE))? (t)(G(a,BITONE)->b) : \+ (t)(G(a,BITTWO)->b))++#define CASTVAR(t,x) ( \+ (test_mode == G(G(PCRE,BITONE),_MODE))? \+ (t)G(x,BITONE) : (t)G(x,BITTWO))++#define CODE_UNIT(a,b) ( \+ (test_mode == G(G(PCRE,BITONE),_MODE))? \+ (uint32_t)(((G(PCRE2_SPTR,BITONE))(a))[b]) : \+ (uint32_t)(((G(PCRE2_SPTR,BITTWO))(a))[b]))++#define CONCTXCPY(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ memcpy(G(a,BITONE),G(b,BITONE),sizeof(G(pcre2_convert_context_,BITONE))); \+ else \+ memcpy(G(a,BITTWO),G(b,BITTWO),sizeof(G(pcre2_convert_context_,BITTWO)))++#define CONVERT_COPY(a,b,c) \+ (test_mode == G(G(PCRE,BITONE),_MODE))? \+ memcpy(G(a,BITONE),(char *)b,(c)*BYTEONE) : \+ memcpy(G(a,BITTWO),(char *)b,(c)*BYTETWO)++#define DATCTXCPY(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ memcpy(G(a,BITONE),G(b,BITONE),sizeof(G(pcre2_match_context_,BITONE))); \+ else \+ memcpy(G(a,BITTWO),G(b,BITTWO),sizeof(G(pcre2_match_context_,BITTWO)))++#define FLD(a,b) \+ ((test_mode == G(G(PCRE,BITONE),_MODE))? G(a,BITONE)->b : G(a,BITTWO)->b)++#define PATCTXCPY(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ memcpy(G(a,BITONE),G(b,BITONE),sizeof(G(pcre2_compile_context_,BITONE))); \+ else \+ memcpy(G(a,BITTWO),G(b,BITTWO),sizeof(G(pcre2_compile_context_,BITTWO)))++#define PCHARS(lv, p, offset, len, utf, f) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ lv = G(pchars,BITONE)((G(PCRE2_SPTR,BITONE))(p)+offset, len, utf, f); \+ else \+ lv = G(pchars,BITTWO)((G(PCRE2_SPTR,BITTWO))(p)+offset, len, utf, f)++#define PCHARSV(p, offset, len, utf, f) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ (void)G(pchars,BITONE)((G(PCRE2_SPTR,BITONE))(p)+offset, len, utf, f); \+ else \+ (void)G(pchars,BITTWO)((G(PCRE2_SPTR,BITTWO))(p)+offset, len, utf, f)++#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_callout_enumerate,BITONE)(G(compiled_code,BITONE), \+ (int (*)(struct G(pcre2_callout_enumerate_block_,BITONE) *, void *))b,c); \+ else \+ a = G(pcre2_callout_enumerate,BITTWO)(G(compiled_code,BITTWO), \+ (int (*)(struct G(pcre2_callout_enumerate_block_,BITTWO) *, void *))b,c)++#define PCRE2_CODE_COPY_FROM_VOID(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(a,BITONE) = G(pcre2_code_copy_,BITONE)(b); \+ else \+ G(a,BITTWO) = G(pcre2_code_copy_,BITTWO)(b)++#define PCRE2_CODE_COPY_TO_VOID(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = (void *)G(pcre2_code_copy_,BITONE)(G(b,BITONE)); \+ else \+ a = (void *)G(pcre2_code_copy_,BITTWO)(G(b,BITTWO))++#define PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = (void *)G(pcre2_code_copy_with_tables_,BITONE)(G(b,BITONE)); \+ else \+ a = (void *)G(pcre2_code_copy_with_tables_,BITTWO)(G(b,BITTWO))++#define PCRE2_COMPILE(a,b,c,d,e,f,g) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(a,BITONE) = G(pcre2_compile_,BITONE)(G(b,BITONE),c,d,e,f,g); \+ else \+ G(a,BITTWO) = G(pcre2_compile_,BITTWO)(G(b,BITTWO),c,d,e,f,g)++#define PCRE2_CONVERTED_PATTERN_FREE(a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_converted_pattern_free_,BITONE)((G(PCRE2_UCHAR,BITONE) *)a); \+ else \+ G(pcre2_converted_pattern_free_,BITTWO)((G(PCRE2_UCHAR,BITTWO) *)a)++#define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_dfa_match_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \+ G(g,BITONE),h,i,j); \+ else \+ a = G(pcre2_dfa_match_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \+ G(g,BITTWO),h,i,j)++#define PCRE2_GET_ERROR_MESSAGE(r,a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ r = G(pcre2_get_error_message_,BITONE)(a,G(b,BITONE),G(G(b,BITONE),_size/BYTEONE)); \+ else \+ r = G(pcre2_get_error_message_,BITTWO)(a,G(b,BITTWO),G(G(b,BITTWO),_size/BYTETWO))++#define PCRE2_GET_OVECTOR_COUNT(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_get_ovector_count_,BITONE)(G(b,BITONE)); \+ else \+ a = G(pcre2_get_ovector_count_,BITTWO)(G(b,BITTWO))++#define PCRE2_GET_STARTCHAR(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_get_startchar_,BITONE)(G(b,BITONE)); \+ else \+ a = G(pcre2_get_startchar_,BITTWO)(G(b,BITTWO))++#define PCRE2_JIT_COMPILE(r,a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ r = G(pcre2_jit_compile_,BITONE)(G(a,BITONE),b); \+ else \+ r = G(pcre2_jit_compile_,BITTWO)(G(a,BITTWO),b)++#define PCRE2_JIT_FREE_UNUSED_MEMORY(a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_jit_free_unused_memory_,BITONE)(G(a,BITONE)); \+ else \+ G(pcre2_jit_free_unused_memory_,BITTWO)(G(a,BITTWO))++#define PCRE2_JIT_MATCH(a,b,c,d,e,f,g,h) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_jit_match_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \+ G(g,BITONE),h); \+ else \+ a = G(pcre2_jit_match_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \+ G(g,BITTWO),h)++#define PCRE2_JIT_STACK_CREATE(a,b,c,d) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = (PCRE2_JIT_STACK *)G(pcre2_jit_stack_create_,BITONE)(b,c,d); \+ else \+ a = (PCRE2_JIT_STACK *)G(pcre2_jit_stack_create_,BITTWO)(b,c,d); \++#define PCRE2_JIT_STACK_ASSIGN(a,b,c) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_jit_stack_assign_,BITONE)(G(a,BITONE),(G(pcre2_jit_callback_,BITONE))b,c); \+ else \+ G(pcre2_jit_stack_assign_,BITTWO)(G(a,BITTWO),(G(pcre2_jit_callback_,BITTWO))b,c);++#define PCRE2_JIT_STACK_FREE(a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_jit_stack_free_,BITONE)((G(pcre2_jit_stack_,BITONE) *)a); \+ else \+ G(pcre2_jit_stack_free_,BITTWO)((G(pcre2_jit_stack_,BITTWO) *)a);++#define PCRE2_MAKETABLES(a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_maketables_,BITONE)(NULL); \+ else \+ a = G(pcre2_maketables_,BITTWO)(NULL)++#define PCRE2_MATCH(a,b,c,d,e,f,g,h) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_match_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \+ G(g,BITONE),h); \+ else \+ a = G(pcre2_match_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \+ G(g,BITTWO),h)++#define PCRE2_MATCH_DATA_CREATE(a,b,c) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(a,BITONE) = G(pcre2_match_data_create_,BITONE)(b,c); \+ else \+ G(a,BITTWO) = G(pcre2_match_data_create_,BITTWO)(b,c)++#define PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(a,b,c) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(a,BITONE) = G(pcre2_match_data_create_from_pattern_,BITONE)(G(b,BITONE),c); \+ else \+ G(a,BITTWO) = G(pcre2_match_data_create_from_pattern_,BITTWO)(G(b,BITTWO),c)++#define PCRE2_MATCH_DATA_FREE(a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_match_data_free_,BITONE)(G(a,BITONE)); \+ else \+ G(pcre2_match_data_free_,BITTWO)(G(a,BITTWO))++#define PCRE2_PATTERN_CONVERT(a,b,c,d,e,f,g) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_pattern_convert_,BITONE)(G(b,BITONE),c,d,(G(PCRE2_UCHAR,BITONE) **)e,f,G(g,BITONE)); \+ else \+ a = G(pcre2_pattern_convert_,BITTWO)(G(b,BITTWO),c,d,(G(PCRE2_UCHAR,BITTWO) **)e,f,G(g,BITTWO))++#define PCRE2_PATTERN_INFO(a,b,c,d) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_pattern_info_,BITONE)(G(b,BITONE),c,d); \+ else \+ a = G(pcre2_pattern_info_,BITTWO)(G(b,BITTWO),c,d)++#define PCRE2_PRINTINT(a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_printint_,BITONE)(G(compiled_code,BITONE),outfile,a); \+ else \+ G(pcre2_printint_,BITTWO)(G(compiled_code,BITTWO),outfile,a)++#define PCRE2_SERIALIZE_DECODE(r,a,b,c,d) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ r = G(pcre2_serialize_decode_,BITONE)((G(pcre2_code_,BITONE) **)a,b,c,G(d,BITONE)); \+ else \+ r = G(pcre2_serialize_decode_,BITTWO)((G(pcre2_code_,BITTWO) **)a,b,c,G(d,BITTWO))++#define PCRE2_SERIALIZE_ENCODE(r,a,b,c,d,e) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ r = G(pcre2_serialize_encode_,BITONE)((G(const pcre2_code_,BITONE) **)a,b,c,d,G(e,BITONE)); \+ else \+ r = G(pcre2_serialize_encode_,BITTWO)((G(const pcre2_code_,BITTWO) **)a,b,c,d,G(e,BITTWO))++#define PCRE2_SERIALIZE_FREE(a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_serialize_free_,BITONE)(a); \+ else \+ G(pcre2_serialize_free_,BITTWO)(a)++#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ r = G(pcre2_serialize_get_number_of_codes_,BITONE)(a); \+ else \+ r = G(pcre2_serialize_get_number_of_codes_,BITTWO)(a)++#define PCRE2_SET_CALLOUT(a,b,c) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_callout_,BITONE)(G(a,BITONE), \+ (int (*)(G(pcre2_callout_block_,BITONE) *, void *))b,c); \+ else \+ G(pcre2_set_callout_,BITTWO)(G(a,BITTWO), \+ (int (*)(G(pcre2_callout_block_,BITTWO) *, void *))b,c);++#define PCRE2_SET_CHARACTER_TABLES(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_character_tables_,BITONE)(G(a,BITONE),b); \+ else \+ G(pcre2_set_character_tables_,BITTWO)(G(a,BITTWO),b)++#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_compile_recursion_guard_,BITONE)(G(a,BITONE),b,c); \+ else \+ G(pcre2_set_compile_recursion_guard_,BITTWO)(G(a,BITTWO),b,c)++#define PCRE2_SET_DEPTH_LIMIT(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_depth_limit_,BITONE)(G(a,BITONE),b); \+ else \+ G(pcre2_set_depth_limit_,BITTWO)(G(a,BITTWO),b)++#define PCRE2_SET_GLOB_ESCAPE(r,a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ r = G(pcre2_set_glob_escape_,BITONE)(G(a,BITONE),b); \+ else \+ r = G(pcre2_set_glob_escape_,BITTWO)(G(a,BITTWO),b)++#define PCRE2_SET_GLOB_SEPARATOR(r,a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ r = G(pcre2_set_glob_separator_,BITONE)(G(a,BITONE),b); \+ else \+ r = G(pcre2_set_glob_separator_,BITTWO)(G(a,BITTWO),b)++#define PCRE2_SET_HEAP_LIMIT(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_heap_limit_,BITONE)(G(a,BITONE),b); \+ else \+ G(pcre2_set_heap_limit_,BITTWO)(G(a,BITTWO),b)++#define PCRE2_SET_MATCH_LIMIT(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_match_limit_,BITONE)(G(a,BITONE),b); \+ else \+ G(pcre2_set_match_limit_,BITTWO)(G(a,BITTWO),b)++#define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_max_pattern_length_,BITONE)(G(a,BITONE),b); \+ else \+ G(pcre2_set_max_pattern_length_,BITTWO)(G(a,BITTWO),b)++#define PCRE2_SET_OFFSET_LIMIT(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_offset_limit_,BITONE)(G(a,BITONE),b); \+ else \+ G(pcre2_set_offset_limit_,BITTWO)(G(a,BITTWO),b)++#define PCRE2_SET_PARENS_NEST_LIMIT(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_parens_nest_limit_,BITONE)(G(a,BITONE),b); \+ else \+ G(pcre2_set_parens_nest_limit_,BITTWO)(G(a,BITTWO),b)++#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_set_substitute_callout_,BITONE)(G(a,BITONE), \+ (int (*)(G(pcre2_substitute_callout_block_,BITONE) *, void *))b,c); \+ else \+ G(pcre2_set_substitute_callout_,BITTWO)(G(a,BITTWO), \+ (int (*)(G(pcre2_substitute_callout_block_,BITTWO) *, void *))b,c)++#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_substitute_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \+ G(g,BITONE),h,(G(PCRE2_SPTR,BITONE))i,j, \+ (G(PCRE2_UCHAR,BITONE) *)k,l); \+ else \+ a = G(pcre2_substitute_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \+ G(g,BITTWO),h,(G(PCRE2_SPTR,BITTWO))i,j, \+ (G(PCRE2_UCHAR,BITTWO) *)k,l)++#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_substring_copy_byname_,BITONE)(G(b,BITONE),G(c,BITONE),\+ (G(PCRE2_UCHAR,BITONE) *)d,e); \+ else \+ a = G(pcre2_substring_copy_byname_,BITTWO)(G(b,BITTWO),G(c,BITTWO),\+ (G(PCRE2_UCHAR,BITTWO) *)d,e)++#define PCRE2_SUBSTRING_COPY_BYNUMBER(a,b,c,d,e) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_substring_copy_bynumber_,BITONE)(G(b,BITONE),c,\+ (G(PCRE2_UCHAR,BITONE) *)d,e); \+ else \+ a = G(pcre2_substring_copy_bynumber_,BITTWO)(G(b,BITTWO),c,\+ (G(PCRE2_UCHAR,BITTWO) *)d,e)++#define PCRE2_SUBSTRING_FREE(a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_substring_free_,BITONE)((G(PCRE2_UCHAR,BITONE) *)a); \+ else G(pcre2_substring_free_,BITTWO)((G(PCRE2_UCHAR,BITTWO) *)a)++#define PCRE2_SUBSTRING_GET_BYNAME(a,b,c,d,e) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_substring_get_byname_,BITONE)(G(b,BITONE),G(c,BITONE),\+ (G(PCRE2_UCHAR,BITONE) **)d,e); \+ else \+ a = G(pcre2_substring_get_byname_,BITTWO)(G(b,BITTWO),G(c,BITTWO),\+ (G(PCRE2_UCHAR,BITTWO) **)d,e)++#define PCRE2_SUBSTRING_GET_BYNUMBER(a,b,c,d,e) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_substring_get_bynumber_,BITONE)(G(b,BITONE),c,\+ (G(PCRE2_UCHAR,BITONE) **)d,e); \+ else \+ a = G(pcre2_substring_get_bynumber_,BITTWO)(G(b,BITTWO),c,\+ (G(PCRE2_UCHAR,BITTWO) **)d,e)++#define PCRE2_SUBSTRING_LENGTH_BYNAME(a,b,c,d) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_substring_length_byname_,BITONE)(G(b,BITONE),G(c,BITONE),d); \+ else \+ a = G(pcre2_substring_length_byname_,BITTWO)(G(b,BITTWO),G(c,BITTWO),d)++#define PCRE2_SUBSTRING_LENGTH_BYNUMBER(a,b,c,d) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_substring_length_bynumber_,BITONE)(G(b,BITONE),c,d); \+ else \+ a = G(pcre2_substring_length_bynumber_,BITTWO)(G(b,BITTWO),c,d)++#define PCRE2_SUBSTRING_LIST_GET(a,b,c,d) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_substring_list_get_,BITONE)(G(b,BITONE), \+ (G(PCRE2_UCHAR,BITONE) ***)c,d); \+ else \+ a = G(pcre2_substring_list_get_,BITTWO)(G(b,BITTWO), \+ (G(PCRE2_UCHAR,BITTWO) ***)c,d)++#define PCRE2_SUBSTRING_LIST_FREE(a) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(pcre2_substring_list_free_,BITONE)((G(PCRE2_SPTR,BITONE) *)a); \+ else \+ G(pcre2_substring_list_free_,BITTWO)((G(PCRE2_SPTR,BITTWO) *)a)++#define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ a = G(pcre2_substring_number_from_name_,BITONE)(G(b,BITONE),G(c,BITONE)); \+ else \+ a = G(pcre2_substring_number_from_name_,BITTWO)(G(b,BITTWO),G(c,BITTWO))++#define PTR(x) ( \+ (test_mode == G(G(PCRE,BITONE),_MODE))? (void *)G(x,BITONE) : \+ (void *)G(x,BITTWO))++#define SETFLD(x,y,z) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) G(x,BITONE)->y = z; \+ else G(x,BITTWO)->y = z++#define SETFLDVEC(x,y,v,z) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) G(x,BITONE)->y[v] = z; \+ else G(x,BITTWO)->y[v] = z++#define SETOP(x,y,z) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) G(x,BITONE) z y; \+ else G(x,BITTWO) z y++#define SETCASTPTR(x,y) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(x,BITONE) = (G(G(uint,BITONE),_t) *)(y); \+ else \+ G(x,BITTWO) = (G(G(uint,BITTWO),_t) *)(y)++#define STRLEN(p) ((test_mode == G(G(PCRE,BITONE),_MODE))? \+ G(strlen,BITONE)((G(PCRE2_SPTR,BITONE))p) : \+ G(strlen,BITTWO)((G(PCRE2_SPTR,BITTWO))p))++#define SUB1(a,b) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(a,BITONE)(G(b,BITONE)); \+ else \+ G(a,BITTWO)(G(b,BITTWO))++#define SUB2(a,b,c) \+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \+ G(a,BITONE))(G(b,BITONE),G(c,BITONE)); \+ else \+ G(a,BITTWO))(G(b,BITTWO),G(c,BITTWO))++#define TEST(x,r,y) ( \+ (test_mode == G(G(PCRE,BITONE),_MODE) && G(x,BITONE) r (y)) || \+ (test_mode == G(G(PCRE,BITTWO),_MODE) && G(x,BITTWO) r (y)))++#define TESTFLD(x,f,r,y) ( \+ (test_mode == G(G(PCRE,BITONE),_MODE) && G(x,BITONE)->f r (y)) || \+ (test_mode == G(G(PCRE,BITTWO),_MODE) && G(x,BITTWO)->f r (y)))+++#endif /* Two out of three modes */++/* ----- End of cases where more than one mode is supported ----- */+++/* ----- Only 8-bit mode is supported ----- */++#elif defined SUPPORT_PCRE2_8+#define CASTFLD(t,a,b) (t)(G(a,8)->b)+#define CASTVAR(t,x) (t)G(x,8)+#define CODE_UNIT(a,b) (uint32_t)(((PCRE2_SPTR8)(a))[b])+#define CONCTXCPY(a,b) memcpy(G(a,8),G(b,8),sizeof(pcre2_convert_context_8))+#define CONVERT_COPY(a,b,c) memcpy(G(a,8),(char *)b, c)+#define DATCTXCPY(a,b) memcpy(G(a,8),G(b,8),sizeof(pcre2_match_context_8))+#define FLD(a,b) G(a,8)->b+#define PATCTXCPY(a,b) memcpy(G(a,8),G(b,8),sizeof(pcre2_compile_context_8))+#define PCHARS(lv, p, offset, len, utf, f) \+ lv = pchars8((PCRE2_SPTR8)(p)+offset, len, utf, f)+#define PCHARSV(p, offset, len, utf, f) \+ (void)pchars8((PCRE2_SPTR8)(p)+offset, len, utf, f)+#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \+ a = pcre2_callout_enumerate_8(compiled_code8, \+ (int (*)(struct pcre2_callout_enumerate_block_8 *, void *))b,c)+#define PCRE2_CODE_COPY_FROM_VOID(a,b) G(a,8) = pcre2_code_copy_8(b)+#define PCRE2_CODE_COPY_TO_VOID(a,b) a = (void *)pcre2_code_copy_8(G(b,8))+#define PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(a,b) a = (void *)pcre2_code_copy_with_tables_8(G(b,8))+#define PCRE2_COMPILE(a,b,c,d,e,f,g) \+ G(a,8) = pcre2_compile_8(G(b,8),c,d,e,f,g)+#define PCRE2_CONVERTED_PATTERN_FREE(a) \+ pcre2_converted_pattern_free_8((PCRE2_UCHAR8 *)a)+#define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \+ a = pcre2_dfa_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h,i,j)+#define PCRE2_GET_ERROR_MESSAGE(r,a,b) \+ r = pcre2_get_error_message_8(a,G(b,8),G(G(b,8),_size))+#define PCRE2_GET_OVECTOR_COUNT(a,b) a = pcre2_get_ovector_count_8(G(b,8))+#define PCRE2_GET_STARTCHAR(a,b) a = pcre2_get_startchar_8(G(b,8))+#define PCRE2_JIT_COMPILE(r,a,b) r = pcre2_jit_compile_8(G(a,8),b)+#define PCRE2_JIT_FREE_UNUSED_MEMORY(a) pcre2_jit_free_unused_memory_8(G(a,8))+#define PCRE2_JIT_MATCH(a,b,c,d,e,f,g,h) \+ a = pcre2_jit_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h)+#define PCRE2_JIT_STACK_CREATE(a,b,c,d) \+ a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_8(b,c,d);+#define PCRE2_JIT_STACK_ASSIGN(a,b,c) \+ pcre2_jit_stack_assign_8(G(a,8),(pcre2_jit_callback_8)b,c);+#define PCRE2_JIT_STACK_FREE(a) pcre2_jit_stack_free_8((pcre2_jit_stack_8 *)a);+#define PCRE2_MAKETABLES(a) a = pcre2_maketables_8(NULL)+#define PCRE2_MATCH(a,b,c,d,e,f,g,h) \+ a = pcre2_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h)+#define PCRE2_MATCH_DATA_CREATE(a,b,c) G(a,8) = pcre2_match_data_create_8(b,c)+#define PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(a,b,c) \+ G(a,8) = pcre2_match_data_create_from_pattern_8(G(b,8),c)+#define PCRE2_MATCH_DATA_FREE(a) pcre2_match_data_free_8(G(a,8))+#define PCRE2_PATTERN_CONVERT(a,b,c,d,e,f,g) a = pcre2_pattern_convert_8(G(b,8),c,d,(PCRE2_UCHAR8 **)e,f,G(g,8))+#define PCRE2_PATTERN_INFO(a,b,c,d) a = pcre2_pattern_info_8(G(b,8),c,d)+#define PCRE2_PRINTINT(a) pcre2_printint_8(compiled_code8,outfile,a)+#define PCRE2_SERIALIZE_DECODE(r,a,b,c,d) \+ r = pcre2_serialize_decode_8((pcre2_code_8 **)a,b,c,G(d,8))+#define PCRE2_SERIALIZE_ENCODE(r,a,b,c,d,e) \+ r = pcre2_serialize_encode_8((const pcre2_code_8 **)a,b,c,d,G(e,8))+#define PCRE2_SERIALIZE_FREE(a) pcre2_serialize_free_8(a)+#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \+ r = pcre2_serialize_get_number_of_codes_8(a)+#define PCRE2_SET_CALLOUT(a,b,c) \+ pcre2_set_callout_8(G(a,8),(int (*)(pcre2_callout_block_8 *, void *))b,c)+#define PCRE2_SET_CHARACTER_TABLES(a,b) pcre2_set_character_tables_8(G(a,8),b)+#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \+ pcre2_set_compile_recursion_guard_8(G(a,8),b,c)+#define PCRE2_SET_DEPTH_LIMIT(a,b) pcre2_set_depth_limit_8(G(a,8),b)+#define PCRE2_SET_GLOB_ESCAPE(r,a,b) r = pcre2_set_glob_escape_8(G(a,8),b)+#define PCRE2_SET_GLOB_SEPARATOR(r,a,b) r = pcre2_set_glob_separator_8(G(a,8),b)+#define PCRE2_SET_HEAP_LIMIT(a,b) pcre2_set_heap_limit_8(G(a,8),b)+#define PCRE2_SET_MATCH_LIMIT(a,b) pcre2_set_match_limit_8(G(a,8),b)+#define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) pcre2_set_max_pattern_length_8(G(a,8),b)+#define PCRE2_SET_OFFSET_LIMIT(a,b) pcre2_set_offset_limit_8(G(a,8),b)+#define PCRE2_SET_PARENS_NEST_LIMIT(a,b) pcre2_set_parens_nest_limit_8(G(a,8),b)+#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \+ pcre2_set_substitute_callout_8(G(a,8), \+ (int (*)(pcre2_substitute_callout_block_8 *, void *))b,c)+#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \+ a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h, \+ (PCRE2_SPTR8)i,j,(PCRE2_UCHAR8 *)k,l)+#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \+ a = pcre2_substring_copy_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 *)d,e)+#define PCRE2_SUBSTRING_COPY_BYNUMBER(a,b,c,d,e) \+ a = pcre2_substring_copy_bynumber_8(G(b,8),c,(PCRE2_UCHAR8 *)d,e)+#define PCRE2_SUBSTRING_FREE(a) pcre2_substring_free_8((PCRE2_UCHAR8 *)a)+#define PCRE2_SUBSTRING_GET_BYNAME(a,b,c,d,e) \+ a = pcre2_substring_get_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 **)d,e)+#define PCRE2_SUBSTRING_GET_BYNUMBER(a,b,c,d,e) \+ a = pcre2_substring_get_bynumber_8(G(b,8),c,(PCRE2_UCHAR8 **)d,e)+#define PCRE2_SUBSTRING_LENGTH_BYNAME(a,b,c,d) \+ a = pcre2_substring_length_byname_8(G(b,8),G(c,8),d)+#define PCRE2_SUBSTRING_LENGTH_BYNUMBER(a,b,c,d) \+ a = pcre2_substring_length_bynumber_8(G(b,8),c,d)+#define PCRE2_SUBSTRING_LIST_GET(a,b,c,d) \+ a = pcre2_substring_list_get_8(G(b,8),(PCRE2_UCHAR8 ***)c,d)+#define PCRE2_SUBSTRING_LIST_FREE(a) \+ pcre2_substring_list_free_8((PCRE2_SPTR8 *)a)+#define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \+ a = pcre2_substring_number_from_name_8(G(b,8),G(c,8));+#define PTR(x) (void *)G(x,8)+#define SETFLD(x,y,z) G(x,8)->y = z+#define SETFLDVEC(x,y,v,z) G(x,8)->y[v] = z+#define SETOP(x,y,z) G(x,8) z y+#define SETCASTPTR(x,y) G(x,8) = (uint8_t *)(y)+#define STRLEN(p) (int)strlen((char *)p)+#define SUB1(a,b) G(a,8)(G(b,8))+#define SUB2(a,b,c) G(a,8)(G(b,8),G(c,8))+#define TEST(x,r,y) (G(x,8) r (y))+#define TESTFLD(x,f,r,y) (G(x,8)->f r (y))+++/* ----- Only 16-bit mode is supported ----- */++#elif defined SUPPORT_PCRE2_16+#define CASTFLD(t,a,b) (t)(G(a,16)->b)+#define CASTVAR(t,x) (t)G(x,16)+#define CODE_UNIT(a,b) (uint32_t)(((PCRE2_SPTR16)(a))[b])+#define CONCTXCPY(a,b) memcpy(G(a,16),G(b,16),sizeof(pcre2_convert_context_16))+#define CONVERT_COPY(a,b,c) memcpy(G(a,16),(char *)b, (c)*2)+#define DATCTXCPY(a,b) memcpy(G(a,16),G(b,16),sizeof(pcre2_match_context_16))+#define FLD(a,b) G(a,16)->b+#define PATCTXCPY(a,b) memcpy(G(a,16),G(b,16),sizeof(pcre2_compile_context_16))+#define PCHARS(lv, p, offset, len, utf, f) \+ lv = pchars16((PCRE2_SPTR16)(p)+offset, len, utf, f)+#define PCHARSV(p, offset, len, utf, f) \+ (void)pchars16((PCRE2_SPTR16)(p)+offset, len, utf, f)+#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \+ a = pcre2_callout_enumerate_16(compiled_code16, \+ (int (*)(struct pcre2_callout_enumerate_block_16 *, void *))b,c)+#define PCRE2_CODE_COPY_FROM_VOID(a,b) G(a,16) = pcre2_code_copy_16(b)+#define PCRE2_CODE_COPY_TO_VOID(a,b) a = (void *)pcre2_code_copy_16(G(b,16))+#define PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(a,b) a = (void *)pcre2_code_copy_with_tables_16(G(b,16))+#define PCRE2_COMPILE(a,b,c,d,e,f,g) \+ G(a,16) = pcre2_compile_16(G(b,16),c,d,e,f,g)+#define PCRE2_CONVERTED_PATTERN_FREE(a) \+ pcre2_converted_pattern_free_16((PCRE2_UCHAR16 *)a)+#define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \+ a = pcre2_dfa_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h,i,j)+#define PCRE2_GET_ERROR_MESSAGE(r,a,b) \+ r = pcre2_get_error_message_16(a,G(b,16),G(G(b,16),_size/2))+#define PCRE2_GET_OVECTOR_COUNT(a,b) a = pcre2_get_ovector_count_16(G(b,16))+#define PCRE2_GET_STARTCHAR(a,b) a = pcre2_get_startchar_16(G(b,16))+#define PCRE2_JIT_COMPILE(r,a,b) r = pcre2_jit_compile_16(G(a,16),b)+#define PCRE2_JIT_FREE_UNUSED_MEMORY(a) pcre2_jit_free_unused_memory_16(G(a,16))+#define PCRE2_JIT_MATCH(a,b,c,d,e,f,g,h) \+ a = pcre2_jit_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h)+#define PCRE2_JIT_STACK_CREATE(a,b,c,d) \+ a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_16(b,c,d);+#define PCRE2_JIT_STACK_ASSIGN(a,b,c) \+ pcre2_jit_stack_assign_16(G(a,16),(pcre2_jit_callback_16)b,c);+#define PCRE2_JIT_STACK_FREE(a) pcre2_jit_stack_free_16((pcre2_jit_stack_16 *)a);+#define PCRE2_MAKETABLES(a) a = pcre2_maketables_16(NULL)+#define PCRE2_MATCH(a,b,c,d,e,f,g,h) \+ a = pcre2_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h)+#define PCRE2_MATCH_DATA_CREATE(a,b,c) G(a,16) = pcre2_match_data_create_16(b,c)+#define PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(a,b,c) \+ G(a,16) = pcre2_match_data_create_from_pattern_16(G(b,16),c)+#define PCRE2_MATCH_DATA_FREE(a) pcre2_match_data_free_16(G(a,16))+#define PCRE2_PATTERN_CONVERT(a,b,c,d,e,f,g) a = pcre2_pattern_convert_16(G(b,16),c,d,(PCRE2_UCHAR16 **)e,f,G(g,16))+#define PCRE2_PATTERN_INFO(a,b,c,d) a = pcre2_pattern_info_16(G(b,16),c,d)+#define PCRE2_PRINTINT(a) pcre2_printint_16(compiled_code16,outfile,a)+#define PCRE2_SERIALIZE_DECODE(r,a,b,c,d) \+ r = pcre2_serialize_decode_16((pcre2_code_16 **)a,b,c,G(d,16))+#define PCRE2_SERIALIZE_ENCODE(r,a,b,c,d,e) \+ r = pcre2_serialize_encode_16((const pcre2_code_16 **)a,b,c,d,G(e,16))+#define PCRE2_SERIALIZE_FREE(a) pcre2_serialize_free_16(a)+#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \+ r = pcre2_serialize_get_number_of_codes_16(a)+#define PCRE2_SET_CALLOUT(a,b,c) \+ pcre2_set_callout_16(G(a,16),(int (*)(pcre2_callout_block_16 *, void *))b,c);+#define PCRE2_SET_CHARACTER_TABLES(a,b) pcre2_set_character_tables_16(G(a,16),b)+#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \+ pcre2_set_compile_recursion_guard_16(G(a,16),b,c)+#define PCRE2_SET_DEPTH_LIMIT(a,b) pcre2_set_depth_limit_16(G(a,16),b)+#define PCRE2_SET_GLOB_ESCAPE(r,a,b) r = pcre2_set_glob_escape_16(G(a,16),b)+#define PCRE2_SET_GLOB_SEPARATOR(r,a,b) r = pcre2_set_glob_separator_16(G(a,16),b)+#define PCRE2_SET_HEAP_LIMIT(a,b) pcre2_set_heap_limit_16(G(a,16),b)+#define PCRE2_SET_MATCH_LIMIT(a,b) pcre2_set_match_limit_16(G(a,16),b)+#define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) pcre2_set_max_pattern_length_16(G(a,16),b)+#define PCRE2_SET_OFFSET_LIMIT(a,b) pcre2_set_offset_limit_16(G(a,16),b)+#define PCRE2_SET_PARENS_NEST_LIMIT(a,b) pcre2_set_parens_nest_limit_16(G(a,16),b)+#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \+ pcre2_set_substitute_callout_16(G(a,16), \+ (int (*)(pcre2_substitute_callout_block_16 *, void *))b,c)+#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \+ a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h, \+ (PCRE2_SPTR16)i,j,(PCRE2_UCHAR16 *)k,l)+#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \+ a = pcre2_substring_copy_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 *)d,e)+#define PCRE2_SUBSTRING_COPY_BYNUMBER(a,b,c,d,e) \+ a = pcre2_substring_copy_bynumber_16(G(b,16),c,(PCRE2_UCHAR16 *)d,e)+#define PCRE2_SUBSTRING_FREE(a) pcre2_substring_free_16((PCRE2_UCHAR16 *)a)+#define PCRE2_SUBSTRING_GET_BYNAME(a,b,c,d,e) \+ a = pcre2_substring_get_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 **)d,e)+#define PCRE2_SUBSTRING_GET_BYNUMBER(a,b,c,d,e) \+ a = pcre2_substring_get_bynumber_16(G(b,16),c,(PCRE2_UCHAR16 **)d,e)+#define PCRE2_SUBSTRING_LENGTH_BYNAME(a,b,c,d) \+ a = pcre2_substring_length_byname_16(G(b,16),G(c,16),d)+#define PCRE2_SUBSTRING_LENGTH_BYNUMBER(a,b,c,d) \+ a = pcre2_substring_length_bynumber_16(G(b,16),c,d)+#define PCRE2_SUBSTRING_LIST_GET(a,b,c,d) \+ a = pcre2_substring_list_get_16(G(b,16),(PCRE2_UCHAR16 ***)c,d)+#define PCRE2_SUBSTRING_LIST_FREE(a) \+ pcre2_substring_list_free_16((PCRE2_SPTR16 *)a)+#define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \+ a = pcre2_substring_number_from_name_16(G(b,16),G(c,16));+#define PTR(x) (void *)G(x,16)+#define SETFLD(x,y,z) G(x,16)->y = z+#define SETFLDVEC(x,y,v,z) G(x,16)->y[v] = z+#define SETOP(x,y,z) G(x,16) z y+#define SETCASTPTR(x,y) G(x,16) = (uint16_t *)(y)+#define STRLEN(p) (int)strlen16((PCRE2_SPTR16)p)+#define SUB1(a,b) G(a,16)(G(b,16))+#define SUB2(a,b,c) G(a,16)(G(b,16),G(c,16))+#define TEST(x,r,y) (G(x,16) r (y))+#define TESTFLD(x,f,r,y) (G(x,16)->f r (y))+++/* ----- Only 32-bit mode is supported ----- */++#elif defined SUPPORT_PCRE2_32+#define CASTFLD(t,a,b) (t)(G(a,32)->b)+#define CASTVAR(t,x) (t)G(x,32)+#define CODE_UNIT(a,b) (uint32_t)(((PCRE2_SPTR32)(a))[b])+#define CONCTXCPY(a,b) memcpy(G(a,32),G(b,32),sizeof(pcre2_convert_context_32))+#define CONVERT_COPY(a,b,c) memcpy(G(a,32),(char *)b, (c)*4)+#define DATCTXCPY(a,b) memcpy(G(a,32),G(b,32),sizeof(pcre2_match_context_32))+#define FLD(a,b) G(a,32)->b+#define PATCTXCPY(a,b) memcpy(G(a,32),G(b,32),sizeof(pcre2_compile_context_32))+#define PCHARS(lv, p, offset, len, utf, f) \+ lv = pchars32((PCRE2_SPTR32)(p)+offset, len, utf, f)+#define PCHARSV(p, offset, len, utf, f) \+ (void)pchars32((PCRE2_SPTR32)(p)+offset, len, utf, f)+#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \+ a = pcre2_callout_enumerate_32(compiled_code32, \+ (int (*)(struct pcre2_callout_enumerate_block_32 *, void *))b,c)+#define PCRE2_CODE_COPY_FROM_VOID(a,b) G(a,32) = pcre2_code_copy_32(b)+#define PCRE2_CODE_COPY_TO_VOID(a,b) a = (void *)pcre2_code_copy_32(G(b,32))+#define PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(a,b) a = (void *)pcre2_code_copy_with_tables_32(G(b,32))+#define PCRE2_COMPILE(a,b,c,d,e,f,g) \+ G(a,32) = pcre2_compile_32(G(b,32),c,d,e,f,g)+#define PCRE2_CONVERTED_PATTERN_FREE(a) \+ pcre2_converted_pattern_free_32((PCRE2_UCHAR32 *)a)+#define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \+ a = pcre2_dfa_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h,i,j)+#define PCRE2_GET_ERROR_MESSAGE(r,a,b) \+ r = pcre2_get_error_message_32(a,G(b,32),G(G(b,32),_size/4))+#define PCRE2_GET_OVECTOR_COUNT(a,b) a = pcre2_get_ovector_count_32(G(b,32))+#define PCRE2_GET_STARTCHAR(a,b) a = pcre2_get_startchar_32(G(b,32))+#define PCRE2_JIT_COMPILE(r,a,b) r = pcre2_jit_compile_32(G(a,32),b)+#define PCRE2_JIT_FREE_UNUSED_MEMORY(a) pcre2_jit_free_unused_memory_32(G(a,32))+#define PCRE2_JIT_MATCH(a,b,c,d,e,f,g,h) \+ a = pcre2_jit_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h)+#define PCRE2_JIT_STACK_CREATE(a,b,c,d) \+ a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_32(b,c,d);+#define PCRE2_JIT_STACK_ASSIGN(a,b,c) \+ pcre2_jit_stack_assign_32(G(a,32),(pcre2_jit_callback_32)b,c);+#define PCRE2_JIT_STACK_FREE(a) pcre2_jit_stack_free_32((pcre2_jit_stack_32 *)a);+#define PCRE2_MAKETABLES(a) a = pcre2_maketables_32(NULL)+#define PCRE2_MATCH(a,b,c,d,e,f,g,h) \+ a = pcre2_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h)+#define PCRE2_MATCH_DATA_CREATE(a,b,c) G(a,32) = pcre2_match_data_create_32(b,c)+#define PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(a,b,c) \+ G(a,32) = pcre2_match_data_create_from_pattern_32(G(b,32),c)+#define PCRE2_MATCH_DATA_FREE(a) pcre2_match_data_free_32(G(a,32))+#define PCRE2_PATTERN_CONVERT(a,b,c,d,e,f,g) a = pcre2_pattern_convert_32(G(b,32),c,d,(PCRE2_UCHAR32 **)e,f,G(g,32))+#define PCRE2_PATTERN_INFO(a,b,c,d) a = pcre2_pattern_info_32(G(b,32),c,d)+#define PCRE2_PRINTINT(a) pcre2_printint_32(compiled_code32,outfile,a)+#define PCRE2_SERIALIZE_DECODE(r,a,b,c,d) \+ r = pcre2_serialize_decode_32((pcre2_code_32 **)a,b,c,G(d,32))+#define PCRE2_SERIALIZE_ENCODE(r,a,b,c,d,e) \+ r = pcre2_serialize_encode_32((const pcre2_code_32 **)a,b,c,d,G(e,32))+#define PCRE2_SERIALIZE_FREE(a) pcre2_serialize_free_32(a)+#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \+ r = pcre2_serialize_get_number_of_codes_32(a)+#define PCRE2_SET_CALLOUT(a,b,c) \+ pcre2_set_callout_32(G(a,32),(int (*)(pcre2_callout_block_32 *, void *))b,c)+#define PCRE2_SET_CHARACTER_TABLES(a,b) pcre2_set_character_tables_32(G(a,32),b)+#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \+ pcre2_set_compile_recursion_guard_32(G(a,32),b,c)+#define PCRE2_SET_DEPTH_LIMIT(a,b) pcre2_set_depth_limit_32(G(a,32),b)+#define PCRE2_SET_GLOB_ESCAPE(r,a,b) r = pcre2_set_glob_escape_32(G(a,32),b)+#define PCRE2_SET_GLOB_SEPARATOR(r,a,b) r = pcre2_set_glob_separator_32(G(a,32),b)+#define PCRE2_SET_HEAP_LIMIT(a,b) pcre2_set_heap_limit_32(G(a,32),b)+#define PCRE2_SET_MATCH_LIMIT(a,b) pcre2_set_match_limit_32(G(a,32),b)+#define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) pcre2_set_max_pattern_length_32(G(a,32),b)+#define PCRE2_SET_OFFSET_LIMIT(a,b) pcre2_set_offset_limit_32(G(a,32),b)+#define PCRE2_SET_PARENS_NEST_LIMIT(a,b) pcre2_set_parens_nest_limit_32(G(a,32),b)+#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \+ pcre2_set_substitute_callout_32(G(a,32), \+ (int (*)(pcre2_substitute_callout_block_32 *, void *))b,c)+#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \+ a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h, \+ (PCRE2_SPTR32)i,j,(PCRE2_UCHAR32 *)k,l)+#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \+ a = pcre2_substring_copy_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 *)d,e)+#define PCRE2_SUBSTRING_COPY_BYNUMBER(a,b,c,d,e) \+ a = pcre2_substring_copy_bynumber_32(G(b,32),c,(PCRE2_UCHAR32 *)d,e);+#define PCRE2_SUBSTRING_FREE(a) pcre2_substring_free_32((PCRE2_UCHAR32 *)a)+#define PCRE2_SUBSTRING_GET_BYNAME(a,b,c,d,e) \+ a = pcre2_substring_get_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 **)d,e)+#define PCRE2_SUBSTRING_GET_BYNUMBER(a,b,c,d,e) \+ a = pcre2_substring_get_bynumber_32(G(b,32),c,(PCRE2_UCHAR32 **)d,e)+#define PCRE2_SUBSTRING_LENGTH_BYNAME(a,b,c,d) \+ a = pcre2_substring_length_byname_32(G(b,32),G(c,32),d)+#define PCRE2_SUBSTRING_LENGTH_BYNUMBER(a,b,c,d) \+ a = pcre2_substring_length_bynumber_32(G(b,32),c,d)+#define PCRE2_SUBSTRING_LIST_GET(a,b,c,d) \+ a = pcre2_substring_list_get_32(G(b,32),(PCRE2_UCHAR32 ***)c,d)+#define PCRE2_SUBSTRING_LIST_FREE(a) \+ pcre2_substring_list_free_32((PCRE2_SPTR32 *)a)+#define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \+ a = pcre2_substring_number_from_name_32(G(b,32),G(c,32));+#define PTR(x) (void *)G(x,32)+#define SETFLD(x,y,z) G(x,32)->y = z+#define SETFLDVEC(x,y,v,z) G(x,32)->y[v] = z+#define SETOP(x,y,z) G(x,32) z y+#define SETCASTPTR(x,y) G(x,32) = (uint32_t *)(y)+#define STRLEN(p) (int)strlen32((PCRE2_SPTR32)p)+#define SUB1(a,b) G(a,32)(G(b,32))+#define SUB2(a,b,c) G(a,32)(G(b,32),G(c,32))+#define TEST(x,r,y) (G(x,32) r (y))+#define TESTFLD(x,f,r,y) (G(x,32)->f r (y))++#endif++/* ----- End of mode-specific function call macros ----- */+++++/*************************************************+* Alternate character tables *+*************************************************/++/* By default, the "tables" pointer in the compile context when calling+pcre2_compile() is not set (= NULL), thereby using the default tables of the+library. However, the tables modifier can be used to select alternate sets of+tables, for different kinds of testing. Note that the locale modifier also+adjusts the tables. */++/* This is the set of tables distributed as default with PCRE2. It recognizes+only ASCII characters. */++static const uint8_t tables1[] = {++/* This table is a lower casing table. */++ 0, 1, 2, 3, 4, 5, 6, 7,+ 8, 9, 10, 11, 12, 13, 14, 15,+ 16, 17, 18, 19, 20, 21, 22, 23,+ 24, 25, 26, 27, 28, 29, 30, 31,+ 32, 33, 34, 35, 36, 37, 38, 39,+ 40, 41, 42, 43, 44, 45, 46, 47,+ 48, 49, 50, 51, 52, 53, 54, 55,+ 56, 57, 58, 59, 60, 61, 62, 63,+ 64, 97, 98, 99,100,101,102,103,+ 104,105,106,107,108,109,110,111,+ 112,113,114,115,116,117,118,119,+ 120,121,122, 91, 92, 93, 94, 95,+ 96, 97, 98, 99,100,101,102,103,+ 104,105,106,107,108,109,110,111,+ 112,113,114,115,116,117,118,119,+ 120,121,122,123,124,125,126,127,+ 128,129,130,131,132,133,134,135,+ 136,137,138,139,140,141,142,143,+ 144,145,146,147,148,149,150,151,+ 152,153,154,155,156,157,158,159,+ 160,161,162,163,164,165,166,167,+ 168,169,170,171,172,173,174,175,+ 176,177,178,179,180,181,182,183,+ 184,185,186,187,188,189,190,191,+ 192,193,194,195,196,197,198,199,+ 200,201,202,203,204,205,206,207,+ 208,209,210,211,212,213,214,215,+ 216,217,218,219,220,221,222,223,+ 224,225,226,227,228,229,230,231,+ 232,233,234,235,236,237,238,239,+ 240,241,242,243,244,245,246,247,+ 248,249,250,251,252,253,254,255,++/* This table is a case flipping table. */++ 0, 1, 2, 3, 4, 5, 6, 7,+ 8, 9, 10, 11, 12, 13, 14, 15,+ 16, 17, 18, 19, 20, 21, 22, 23,+ 24, 25, 26, 27, 28, 29, 30, 31,+ 32, 33, 34, 35, 36, 37, 38, 39,+ 40, 41, 42, 43, 44, 45, 46, 47,+ 48, 49, 50, 51, 52, 53, 54, 55,+ 56, 57, 58, 59, 60, 61, 62, 63,+ 64, 97, 98, 99,100,101,102,103,+ 104,105,106,107,108,109,110,111,+ 112,113,114,115,116,117,118,119,+ 120,121,122, 91, 92, 93, 94, 95,+ 96, 65, 66, 67, 68, 69, 70, 71,+ 72, 73, 74, 75, 76, 77, 78, 79,+ 80, 81, 82, 83, 84, 85, 86, 87,+ 88, 89, 90,123,124,125,126,127,+ 128,129,130,131,132,133,134,135,+ 136,137,138,139,140,141,142,143,+ 144,145,146,147,148,149,150,151,+ 152,153,154,155,156,157,158,159,+ 160,161,162,163,164,165,166,167,+ 168,169,170,171,172,173,174,175,+ 176,177,178,179,180,181,182,183,+ 184,185,186,187,188,189,190,191,+ 192,193,194,195,196,197,198,199,+ 200,201,202,203,204,205,206,207,+ 208,209,210,211,212,213,214,215,+ 216,217,218,219,220,221,222,223,+ 224,225,226,227,228,229,230,231,+ 232,233,234,235,236,237,238,239,+ 240,241,242,243,244,245,246,247,+ 248,249,250,251,252,253,254,255,++/* This table contains bit maps for various character classes. Each map is 32+bytes long and the bits run from the least significant end of each byte. The+classes that have their own maps are: space, xdigit, digit, upper, lower, word,+graph, print, punct, and cntrl. Other classes are built from combinations. */++ 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,+ 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,+ 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,+ 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++/* This table identifies various classes of character by individual bits:+ 0x01 white space character+ 0x02 letter+ 0x04 decimal digit+ 0x08 hexadecimal digit+ 0x10 alphanumeric or '_'+ 0x80 regular expression metacharacter or binary zero+*/++ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */+ 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */+ 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */+ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */+ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */+ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */+ 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */+ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */+ 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */++/* This is a set of tables that came originally from a Windows user. It seems+to be at least an approximation of ISO 8859. In particular, there are+characters greater than 128 that are marked as spaces, letters, etc. */++static const uint8_t tables2[] = {+0,1,2,3,4,5,6,7,+8,9,10,11,12,13,14,15,+16,17,18,19,20,21,22,23,+24,25,26,27,28,29,30,31,+32,33,34,35,36,37,38,39,+40,41,42,43,44,45,46,47,+48,49,50,51,52,53,54,55,+56,57,58,59,60,61,62,63,+64,97,98,99,100,101,102,103,+104,105,106,107,108,109,110,111,+112,113,114,115,116,117,118,119,+120,121,122,91,92,93,94,95,+96,97,98,99,100,101,102,103,+104,105,106,107,108,109,110,111,+112,113,114,115,116,117,118,119,+120,121,122,123,124,125,126,127,+128,129,130,131,132,133,134,135,+136,137,138,139,140,141,142,143,+144,145,146,147,148,149,150,151,+152,153,154,155,156,157,158,159,+160,161,162,163,164,165,166,167,+168,169,170,171,172,173,174,175,+176,177,178,179,180,181,182,183,+184,185,186,187,188,189,190,191,+224,225,226,227,228,229,230,231,+232,233,234,235,236,237,238,239,+240,241,242,243,244,245,246,215,+248,249,250,251,252,253,254,223,+224,225,226,227,228,229,230,231,+232,233,234,235,236,237,238,239,+240,241,242,243,244,245,246,247,+248,249,250,251,252,253,254,255,+0,1,2,3,4,5,6,7,+8,9,10,11,12,13,14,15,+16,17,18,19,20,21,22,23,+24,25,26,27,28,29,30,31,+32,33,34,35,36,37,38,39,+40,41,42,43,44,45,46,47,+48,49,50,51,52,53,54,55,+56,57,58,59,60,61,62,63,+64,97,98,99,100,101,102,103,+104,105,106,107,108,109,110,111,+112,113,114,115,116,117,118,119,+120,121,122,91,92,93,94,95,+96,65,66,67,68,69,70,71,+72,73,74,75,76,77,78,79,+80,81,82,83,84,85,86,87,+88,89,90,123,124,125,126,127,+128,129,130,131,132,133,134,135,+136,137,138,139,140,141,142,143,+144,145,146,147,148,149,150,151,+152,153,154,155,156,157,158,159,+160,161,162,163,164,165,166,167,+168,169,170,171,172,173,174,175,+176,177,178,179,180,181,182,183,+184,185,186,187,188,189,190,191,+224,225,226,227,228,229,230,231,+232,233,234,235,236,237,238,239,+240,241,242,243,244,245,246,215,+248,249,250,251,252,253,254,223,+192,193,194,195,196,197,198,199,+200,201,202,203,204,205,206,207,+208,209,210,211,212,213,214,247,+216,217,218,219,220,221,222,255,+0,62,0,0,1,0,0,0,+0,0,0,0,0,0,0,0,+32,0,0,0,1,0,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,255,3,+126,0,0,0,126,0,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,255,3,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,12,2,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,0,0,+254,255,255,7,0,0,0,0,+0,0,0,0,0,0,0,0,+255,255,127,127,0,0,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,254,255,255,7,+0,0,0,0,0,4,32,4,+0,0,0,128,255,255,127,255,+0,0,0,0,0,0,255,3,+254,255,255,135,254,255,255,7,+0,0,0,0,0,4,44,6,+255,255,127,255,255,255,127,255,+0,0,0,0,254,255,255,255,+255,255,255,255,255,255,255,127,+0,0,0,0,254,255,255,255,+255,255,255,255,255,255,255,255,+0,2,0,0,255,255,255,255,+255,255,255,255,255,255,255,127,+0,0,0,0,255,255,255,255,+255,255,255,255,255,255,255,255,+0,0,0,0,254,255,0,252,+1,0,0,248,1,0,0,120,+0,0,0,0,254,255,255,255,+0,0,128,0,0,0,128,0,+255,255,255,255,0,0,0,0,+0,0,0,0,0,0,0,128,+255,255,255,255,0,0,0,0,+0,0,0,0,0,0,0,0,+128,0,0,0,0,0,0,0,+0,1,1,0,1,1,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,0,0,+1,0,0,0,128,0,0,0,+128,128,128,128,0,0,128,0,+28,28,28,28,28,28,28,28,+28,28,0,0,0,0,0,128,+0,26,26,26,26,26,26,18,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,18,+18,18,18,128,128,0,128,16,+0,26,26,26,26,26,26,18,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,18,+18,18,18,128,128,0,0,0,+0,0,0,0,0,1,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,0,0,+1,0,0,0,0,0,0,0,+0,0,18,0,0,0,0,0,+0,0,20,20,0,18,0,0,+0,20,18,0,0,0,0,0,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,0,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,0,+18,18,18,18,18,18,18,18+};++++#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)+/*************************************************+* Emulated memmove() for systems without it *+*************************************************/++/* This function can make use of bcopy() if it is available. Otherwise do it by+steam, as there are some non-Unix environments that lack both memmove() and+bcopy(). */++static void *+emulated_memmove(void *d, const void *s, size_t n)+{+#ifdef HAVE_BCOPY+bcopy(s, d, n);+return d;+#else+size_t i;+unsigned char *dest = (unsigned char *)d;+const unsigned char *src = (const unsigned char *)s;+if (dest > src)+ {+ dest += n;+ src += n;+ for (i = 0; i < n; ++i) *(--dest) = *(--src);+ return (void *)dest;+ }+else+ {+ for (i = 0; i < n; ++i) *dest++ = *src++;+ return (void *)(dest - n);+ }+#endif /* not HAVE_BCOPY */+}+#undef memmove+#define memmove(d,s,n) emulated_memmove(d,s,n)+#endif /* not VPCOMPAT && not HAVE_MEMMOVE */++++#ifndef HAVE_STRERROR+/*************************************************+* Provide strerror() for non-ANSI libraries *+*************************************************/++/* Some old-fashioned systems (e.g. SunOS4) didn't have strerror() in their+libraries. They may no longer be around, but just in case, we can try to+provide the same facility by this simple alternative function. */++extern int sys_nerr;+extern char *sys_errlist[];++char *+strerror(int n)+{+if (n < 0 || n >= sys_nerr) return "unknown error number";+return sys_errlist[n];+}+#endif /* HAVE_STRERROR */++++/*************************************************+* Local memory functions *+*************************************************/++/* Alternative memory functions, to test functionality. */++static void *my_malloc(PCRE2_SIZE size, void *data)+{+void *block = malloc(size);+(void)data;+if (show_memory)+ {+ if (block == NULL)+ {+ fprintf(outfile, "** malloc() failed for %" SIZ_FORM "\n", SIZ_CAST size);+ }+ else+ {+ fprintf(outfile, "malloc %5" SIZ_FORM, SIZ_CAST size);+#ifdef DEBUG_SHOW_MALLOC_ADDRESSES+ fprintf(outfile, " %p", block); /* Not portable */+#endif+ if (malloclistptr < MALLOCLISTSIZE)+ {+ malloclist[malloclistptr] = block;+ malloclistlength[malloclistptr++] = size;+ }+ else+ fprintf(outfile, " (not remembered)");+ fprintf(outfile, "\n");+ }+ }+return block;+}++static void my_free(void *block, void *data)+{+(void)data;+if (show_memory)+ {+ uint32_t i, j;+ BOOL found = FALSE;++ fprintf(outfile, "free");+ for (i = 0; i < malloclistptr; i++)+ {+ if (block == malloclist[i])+ {+ fprintf(outfile, " %5" SIZ_FORM, SIZ_CAST malloclistlength[i]);+ malloclistptr--;+ for (j = i; j < malloclistptr; j++)+ {+ malloclist[j] = malloclist[j+1];+ malloclistlength[j] = malloclistlength[j+1];+ }+ found = TRUE;+ break;+ }+ }+ if (!found) fprintf(outfile, " unremembered block");+#ifdef DEBUG_SHOW_MALLOC_ADDRESSES+ fprintf(outfile, " %p", block); /* Not portable */+#endif+ fprintf(outfile, "\n");+ }+free(block);+}++++/*************************************************+* Callback function for stack guard *+*************************************************/++/* This is set up to be called from pcre2_compile() when the stackguard=n+modifier sets a value greater than zero. The test we do is whether the+parenthesis nesting depth is greater than the value set by the modifier.++Argument: the current parenthesis nesting depth+Returns: non-zero to kill the compilation+*/++static int+stack_guard(uint32_t depth, void *user_data)+{+(void)user_data;+return depth > pat_patctl.stackguard_test;+}+++/*************************************************+* JIT memory callback *+*************************************************/++static PCRE2_JIT_STACK*+jit_callback(void *arg)+{+jit_was_used = TRUE;+return (PCRE2_JIT_STACK *)arg;+}+++/*************************************************+* Convert UTF-8 character to code point *+*************************************************/++/* This function reads one or more bytes that represent a UTF-8 character,+and returns the codepoint of that character. Note that the function supports+the original UTF-8 definition of RFC 2279, allowing for values in the range 0+to 0x7fffffff, up to 6 bytes long. This makes it possible to generate+codepoints greater than 0x10ffff which are useful for testing PCRE2's error+checking, and also for generating 32-bit non-UTF data values above the UTF+limit.++Argument:+ utf8bytes a pointer to the byte vector+ vptr a pointer to an int to receive the value++Returns: > 0 => the number of bytes consumed+ -6 to 0 => malformed UTF-8 character at offset = (-return)+*/++static int+utf82ord(PCRE2_SPTR8 utf8bytes, uint32_t *vptr)+{+uint32_t c = *utf8bytes++;+uint32_t d = c;+int i, j, s;++for (i = -1; i < 6; i++) /* i is number of additional bytes */+ {+ if ((d & 0x80) == 0) break;+ d <<= 1;+ }++if (i == -1) { *vptr = c; return 1; } /* ascii character */+if (i == 0 || i == 6) return 0; /* invalid UTF-8 */++/* i now has a value in the range 1-5 */++s = 6*i;+d = (c & utf8_table3[i]) << s;++for (j = 0; j < i; j++)+ {+ c = *utf8bytes++;+ if ((c & 0xc0) != 0x80) return -(j+1);+ s -= 6;+ d |= (c & 0x3f) << s;+ }++/* Check that encoding was the correct unique one */++for (j = 0; j < utf8_table1_size; j++)+ if (d <= (uint32_t)utf8_table1[j]) break;+if (j != i) return -(i+1);++/* Valid value */++*vptr = d;+return i+1;+}++++/*************************************************+* Print one character *+*************************************************/++/* Print a single character either literally, or as a hex escape, and count how+many printed characters are used.++Arguments:+ c the character+ utf TRUE in UTF mode+ f the FILE to print to, or NULL just to count characters++Returns: number of characters written+*/++static int+pchar(uint32_t c, BOOL utf, FILE *f)+{+int n = 0;+char tempbuffer[16];++if (PRINTOK(c))+ {+ if (f != NULL) fprintf(f, "%c", c);+ return 1;+ }++if (c < 0x100)+ {+ if (utf)+ {+ if (f != NULL) fprintf(f, "\\x{%02x}", c);+ return 6;+ }+ else+ {+ if (f != NULL) fprintf(f, "\\x%02x", c);+ return 4;+ }+ }++if (f != NULL) n = fprintf(f, "\\x{%02x}", c);+ else n = sprintf(tempbuffer, "\\x{%02x}", c);++return n >= 0 ? n : 0;+}++++#ifdef SUPPORT_PCRE2_16+/*************************************************+* Find length of 0-terminated 16-bit string *+*************************************************/++static size_t strlen16(PCRE2_SPTR16 p)+{+PCRE2_SPTR16 pp = p;+while (*pp != 0) pp++;+return (int)(pp - p);+}+#endif /* SUPPORT_PCRE2_16 */++++#ifdef SUPPORT_PCRE2_32+/*************************************************+* Find length of 0-terminated 32-bit string *+*************************************************/++static size_t strlen32(PCRE2_SPTR32 p)+{+PCRE2_SPTR32 pp = p;+while (*pp != 0) pp++;+return (int)(pp - p);+}+#endif /* SUPPORT_PCRE2_32 */+++#ifdef SUPPORT_PCRE2_8+/*************************************************+* Print 8-bit character string *+*************************************************/++/* Must handle UTF-8 strings in utf8 mode. Yields number of characters printed.+For printing *MARK strings, a negative length is given, indicating that the+length is in the first code unit. If handed a NULL file, this function just+counts chars without printing (because pchar() does that). */++static int pchars8(PCRE2_SPTR8 p, int length, BOOL utf, FILE *f)+{+uint32_t c = 0;+int yield = 0;+if (length < 0) length = *p++;+while (length-- > 0)+ {+ if (utf)+ {+ int rc = utf82ord(p, &c);+ if (rc > 0 && rc <= length + 1) /* Mustn't run over the end */+ {+ length -= rc - 1;+ p += rc;+ yield += pchar(c, utf, f);+ continue;+ }+ }+ c = *p++;+ yield += pchar(c, utf, f);+ }++return yield;+}+#endif+++#ifdef SUPPORT_PCRE2_16+/*************************************************+* Print 16-bit character string *+*************************************************/++/* Must handle UTF-16 strings in utf mode. Yields number of characters printed.+For printing *MARK strings, a negative length is given, indicating that the+length is in the first code unit. If handed a NULL file, just counts chars+without printing. */++static int pchars16(PCRE2_SPTR16 p, int length, BOOL utf, FILE *f)+{+int yield = 0;+if (length < 0) length = *p++;+while (length-- > 0)+ {+ uint32_t c = *p++ & 0xffff;+ if (utf && c >= 0xD800 && c < 0xDC00 && length > 0)+ {+ int d = *p & 0xffff;+ if (d >= 0xDC00 && d <= 0xDFFF)+ {+ c = ((c & 0x3ff) << 10) + (d & 0x3ff) + 0x10000;+ length--;+ p++;+ }+ }+ yield += pchar(c, utf, f);+ }+return yield;+}+#endif /* SUPPORT_PCRE2_16 */++++#ifdef SUPPORT_PCRE2_32+/*************************************************+* Print 32-bit character string *+*************************************************/++/* Must handle UTF-32 strings in utf mode. Yields number of characters printed.+For printing *MARK strings, a negative length is given, indicating that the+length is in the first code unit. If handed a NULL file, just counts chars+without printing. */++static int pchars32(PCRE2_SPTR32 p, int length, BOOL utf, FILE *f)+{+int yield = 0;+(void)(utf); /* Avoid compiler warning */+if (length < 0) length = *p++;+while (length-- > 0)+ {+ uint32_t c = *p++;+ yield += pchar(c, utf, f);+ }+return yield;+}+#endif /* SUPPORT_PCRE2_32 */+++++/*************************************************+* Convert character value to UTF-8 *+*************************************************/++/* This function takes an integer value in the range 0 - 0x7fffffff+and encodes it as a UTF-8 character in 0 to 6 bytes. It is needed even when the+8-bit library is not supported, to generate UTF-8 output for non-ASCII+characters.++Arguments:+ cvalue the character value+ utf8bytes pointer to buffer for result - at least 6 bytes long++Returns: number of characters placed in the buffer+*/++static int+ord2utf8(uint32_t cvalue, uint8_t *utf8bytes)+{+int i, j;+if (cvalue > 0x7fffffffu)+ return -1;+for (i = 0; i < utf8_table1_size; i++)+ if (cvalue <= (uint32_t)utf8_table1[i]) break;+utf8bytes += i;+for (j = i; j > 0; j--)+ {+ *utf8bytes-- = 0x80 | (cvalue & 0x3f);+ cvalue >>= 6;+ }+*utf8bytes = utf8_table2[i] | cvalue;+return i + 1;+}++++#ifdef SUPPORT_PCRE2_16+/*************************************************+* Convert string to 16-bit *+*************************************************/++/* In UTF mode the input is always interpreted as a string of UTF-8 bytes using+the original UTF-8 definition of RFC 2279, which allows for up to 6 bytes, and+code values from 0 to 0x7fffffff. However, values greater than the later UTF+limit of 0x10ffff cause an error. In non-UTF mode the input is interpreted as+UTF-8 if the utf8_input modifier is set, but an error is generated for values+greater than 0xffff.++If all the input bytes are ASCII, the space needed for a 16-bit string is+exactly double the 8-bit size. Otherwise, the size needed for a 16-bit string+is no more than double, because up to 0xffff uses no more than 3 bytes in UTF-8+but possibly 4 in UTF-16. Higher values use 4 bytes in UTF-8 and up to 4 bytes+in UTF-16. The result is always left in pbuffer16. Impose a minimum size to+save repeated re-sizing.++Note that this function does not object to surrogate values. This is+deliberate; it makes it possible to construct UTF-16 strings that are invalid,+for the purpose of testing that they are correctly faulted.++Arguments:+ p points to a byte string+ utf true in UTF mode+ lenptr points to number of bytes in the string (excluding trailing zero)++Returns: 0 on success, with the length updated to the number of 16-bit+ data items used (excluding the trailing zero)+ OR -1 if a UTF-8 string is malformed+ OR -2 if a value > 0x10ffff is encountered in UTF mode+ OR -3 if a value > 0xffff is encountered when not in UTF mode+*/++static PCRE2_SIZE+to16(uint8_t *p, int utf, PCRE2_SIZE *lenptr)+{+uint16_t *pp;+PCRE2_SIZE len = *lenptr;++if (pbuffer16_size < 2*len + 2)+ {+ if (pbuffer16 != NULL) free(pbuffer16);+ pbuffer16_size = 2*len + 2;+ if (pbuffer16_size < 4096) pbuffer16_size = 4096;+ pbuffer16 = (uint16_t *)malloc(pbuffer16_size);+ if (pbuffer16 == NULL)+ {+ fprintf(stderr, "pcre2test: malloc(%" SIZ_FORM ") failed for pbuffer16\n",+ SIZ_CAST pbuffer16_size);+ exit(1);+ }+ }++pp = pbuffer16;+if (!utf && (pat_patctl.control & CTL_UTF8_INPUT) == 0)+ {+ for (; len > 0; len--) *pp++ = *p++;+ }+else while (len > 0)+ {+ uint32_t c;+ int chlen = utf82ord(p, &c);+ if (chlen <= 0) return -1;+ if (!utf && c > 0xffff) return -3;+ if (c > 0x10ffff) return -2;+ p += chlen;+ len -= chlen;+ if (c < 0x10000) *pp++ = c; else+ {+ c -= 0x10000;+ *pp++ = 0xD800 | (c >> 10);+ *pp++ = 0xDC00 | (c & 0x3ff);+ }+ }++*pp = 0;+*lenptr = pp - pbuffer16;+return 0;+}+#endif++++#ifdef SUPPORT_PCRE2_32+/*************************************************+* Convert string to 32-bit *+*************************************************/++/* In UTF mode the input is always interpreted as a string of UTF-8 bytes using+the original UTF-8 definition of RFC 2279, which allows for up to 6 bytes, and+code values from 0 to 0x7fffffff. However, values greater than the later UTF+limit of 0x10ffff cause an error.++In non-UTF mode the input is interpreted as UTF-8 if the utf8_input modifier+is set, and no limit is imposed. There is special interpretation of the 0xff+byte (which is illegal in UTF-8) in this case: it causes the top bit of the+next character to be set. This provides a way of generating 32-bit characters+greater than 0x7fffffff.++If all the input bytes are ASCII, the space needed for a 32-bit string is+exactly four times the 8-bit size. Otherwise, the size needed for a 32-bit+string is no more than four times, because the number of characters must be+less than the number of bytes. The result is always left in pbuffer32. Impose a+minimum size to save repeated re-sizing.++Note that this function does not object to surrogate values. This is+deliberate; it makes it possible to construct UTF-32 strings that are invalid,+for the purpose of testing that they are correctly faulted.++Arguments:+ p points to a byte string+ utf true in UTF mode+ lenptr points to number of bytes in the string (excluding trailing zero)++Returns: 0 on success, with the length updated to the number of 32-bit+ data items used (excluding the trailing zero)+ OR -1 if a UTF-8 string is malformed+ OR -2 if a value > 0x10ffff is encountered in UTF mode+*/++static PCRE2_SIZE+to32(uint8_t *p, int utf, PCRE2_SIZE *lenptr)+{+uint32_t *pp;+PCRE2_SIZE len = *lenptr;++if (pbuffer32_size < 4*len + 4)+ {+ if (pbuffer32 != NULL) free(pbuffer32);+ pbuffer32_size = 4*len + 4;+ if (pbuffer32_size < 8192) pbuffer32_size = 8192;+ pbuffer32 = (uint32_t *)malloc(pbuffer32_size);+ if (pbuffer32 == NULL)+ {+ fprintf(stderr, "pcre2test: malloc(%" SIZ_FORM ") failed for pbuffer32\n",+ SIZ_CAST pbuffer32_size);+ exit(1);+ }+ }++pp = pbuffer32;++if (!utf && (pat_patctl.control & CTL_UTF8_INPUT) == 0)+ {+ for (; len > 0; len--) *pp++ = *p++;+ }++else while (len > 0)+ {+ int chlen;+ uint32_t c;+ uint32_t topbit = 0;+ if (!utf && *p == 0xff && len > 1)+ {+ topbit = 0x80000000u;+ p++;+ len--;+ }+ chlen = utf82ord(p, &c);+ if (chlen <= 0) return -1;+ if (utf && c > 0x10ffff) return -2;+ p += chlen;+ len -= chlen;+ *pp++ = c | topbit;+ }++*pp = 0;+*lenptr = pp - pbuffer32;+return 0;+}+#endif /* SUPPORT_PCRE2_32 */++++/* This function is no longer used. Keep it around for a while, just in case it+needs to be re-instated. */++#ifdef NEVERNEVERNEVER++/*************************************************+* Move back by so many characters *+*************************************************/++/* Given a code unit offset in a subject string, move backwards by a number of+characters, and return the resulting offset.++Arguments:+ subject pointer to the string+ offset start offset+ count count to move back by+ utf TRUE if in UTF mode++Returns: a possibly changed offset+*/++static PCRE2_SIZE+backchars(uint8_t *subject, PCRE2_SIZE offset, uint32_t count, BOOL utf)+{+if (!utf || test_mode == PCRE32_MODE)+ return (count >= offset)? 0 : (offset - count);++else if (test_mode == PCRE8_MODE)+ {+ PCRE2_SPTR8 pp = (PCRE2_SPTR8)subject + offset;+ for (; count > 0 && pp > (PCRE2_SPTR8)subject; count--)+ {+ pp--;+ while ((*pp & 0xc0) == 0x80) pp--;+ }+ return pp - (PCRE2_SPTR8)subject;+ }++else /* 16-bit mode */+ {+ PCRE2_SPTR16 pp = (PCRE2_SPTR16)subject + offset;+ for (; count > 0 && pp > (PCRE2_SPTR16)subject; count--)+ {+ pp--;+ if ((*pp & 0xfc00) == 0xdc00) pp--;+ }+ return pp - (PCRE2_SPTR16)subject;+ }+}+#endif /* NEVERNEVERNEVER */++++/*************************************************+* Expand input buffers *+*************************************************/++/* This function doubles the size of the input buffer and the buffer for+keeping an 8-bit copy of patterns (pbuffer8), and copies the current buffers to+the new ones.++Arguments: none+Returns: nothing (aborts if malloc() fails)+*/++static void+expand_input_buffers(void)+{+int new_pbuffer8_size = 2*pbuffer8_size;+uint8_t *new_buffer = (uint8_t *)malloc(new_pbuffer8_size);+uint8_t *new_pbuffer8 = (uint8_t *)malloc(new_pbuffer8_size);++if (new_buffer == NULL || new_pbuffer8 == NULL)+ {+ fprintf(stderr, "pcre2test: malloc(%d) failed\n", new_pbuffer8_size);+ exit(1);+ }++memcpy(new_buffer, buffer, pbuffer8_size);+memcpy(new_pbuffer8, pbuffer8, pbuffer8_size);++pbuffer8_size = new_pbuffer8_size;++free(buffer);+free(pbuffer8);++buffer = new_buffer;+pbuffer8 = new_pbuffer8;+}++++/*************************************************+* Read or extend an input line *+*************************************************/++/* Input lines are read into buffer, but both patterns and data lines can be+continued over multiple input lines. In addition, if the buffer fills up, we+want to automatically expand it so as to be able to handle extremely large+lines that are needed for certain stress tests, although this is less likely+now that there are repetition features for both patterns and data. When the+input buffer is expanded, the other two buffers must also be expanded likewise,+and the contents of pbuffer, which are a copy of the input for callouts, must+be preserved (for when expansion happens for a data line). This is not the most+optimal way of handling this, but hey, this is just a test program!++Arguments:+ f the file to read+ start where in buffer to start (this *must* be within buffer)+ prompt for stdin or readline()++Returns: pointer to the start of new data+ could be a copy of start, or could be moved+ NULL if no data read and EOF reached+*/++static uint8_t *+extend_inputline(FILE *f, uint8_t *start, const char *prompt)+{+uint8_t *here = start;++for (;;)+ {+ size_t rlen = (size_t)(pbuffer8_size - (here - buffer));++ if (rlen > 1000)+ {+ size_t dlen;++ /* If libreadline or libedit support is required, use readline() to read a+ line if the input is a terminal. Note that readline() removes the trailing+ newline, so we must put it back again, to be compatible with fgets(). */++#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+ if (INTERACTIVE(f))+ {+ size_t len;+ char *s = readline(prompt);+ if (s == NULL) return (here == start)? NULL : start;+ len = strlen(s);+ if (len > 0) add_history(s);+ if (len > rlen - 1) len = rlen - 1;+ memcpy(here, s, len);+ here[len] = '\n';+ here[len+1] = 0;+ free(s);+ }+ else+#endif++ /* Read the next line by normal means, prompting if the file is a tty. */++ {+ if (INTERACTIVE(f)) printf("%s", prompt);+ if (fgets((char *)here, rlen, f) == NULL)+ return (here == start)? NULL : start;+ }++ dlen = strlen((char *)here);+ here += dlen;++ /* Check for end of line reached. Take care not to read data from before+ start (dlen will be zero for a file starting with a binary zero). */++ if (here > start && here[-1] == '\n') return start;++ /* If we have not read a newline when reading a file, we have either filled+ the buffer or reached the end of the file. We can detect the former by+ checking that the string fills the buffer, and the latter by feof(). If+ neither of these is true, it means we read a binary zero which has caused+ strlen() to give a short length. This is a hard error because pcre2test+ expects to work with C strings. */++ if (!INTERACTIVE(f) && dlen < rlen - 1 && !feof(f))+ {+ fprintf(outfile, "** Binary zero encountered in input\n");+ fprintf(outfile, "** pcre2test run abandoned\n");+ exit(1);+ }+ }++ else+ {+ size_t start_offset = start - buffer;+ size_t here_offset = here - buffer;+ expand_input_buffers();+ start = buffer + start_offset;+ here = buffer + here_offset;+ }+ }++/* Control never gets here */+}++++/*************************************************+* Case-independent strncmp() function *+*************************************************/++/*+Arguments:+ s first string+ t second string+ n number of characters to compare++Returns: < 0, = 0, or > 0, according to the comparison+*/++static int+strncmpic(const uint8_t *s, const uint8_t *t, int n)+{+while (n--)+ {+ int c = tolower(*s++) - tolower(*t++);+ if (c != 0) return c;+ }+return 0;+}++++/*************************************************+* Scan the main modifier list *+*************************************************/++/* This function searches the modifier list for a long modifier name.++Argument:+ p start of the name+ lenp length of the name++Returns: an index in the modifier list, or -1 on failure+*/++static int+scan_modifiers(const uint8_t *p, unsigned int len)+{+int bot = 0;+int top = MODLISTCOUNT;++while (top > bot)+ {+ int mid = (bot + top)/2;+ unsigned int mlen = strlen(modlist[mid].name);+ int c = strncmp((char *)p, modlist[mid].name, (len < mlen)? len : mlen);+ if (c == 0)+ {+ if (len == mlen) return mid;+ c = (int)len - (int)mlen;+ }+ if (c > 0) bot = mid + 1; else top = mid;+ }++return -1;++}++++/*************************************************+* Check a modifer and find its field *+*************************************************/++/* This function is called when a modifier has been identified. We check that+it is allowed here and find the field that is to be changed.++Arguments:+ m the modifier list entry+ ctx CTX_PAT => pattern context+ CTX_POPPAT => pattern context for popped pattern+ CTX_DEFPAT => default pattern context+ CTX_DAT => data context+ CTX_DEFDAT => default data context+ pctl point to pattern control block+ dctl point to data control block+ c a single character or 0++Returns: a field pointer or NULL+*/++static void *+check_modifier(modstruct *m, int ctx, patctl *pctl, datctl *dctl, uint32_t c)+{+void *field = NULL;+PCRE2_SIZE offset = m->offset;++if (restrict_for_perl_test) switch(m->which)+ {+ case MOD_PNDP:+ case MOD_PATP:+ case MOD_PDP:+ break;++ default:+ fprintf(outfile, "** '%s' is not allowed in a Perl-compatible test\n",+ m->name);+ return NULL;+ }++switch (m->which)+ {+ case MOD_CTC: /* Compile context modifier */+ if (ctx == CTX_DEFPAT) field = PTR(default_pat_context);+ else if (ctx == CTX_PAT) field = PTR(pat_context);+ break;++ case MOD_CTM: /* Match context modifier */+ if (ctx == CTX_DEFDAT) field = PTR(default_dat_context);+ else if (ctx == CTX_DAT) field = PTR(dat_context);+ break;++ case MOD_DAT: /* Data line modifier */+ if (dctl != NULL) field = dctl;+ break;++ case MOD_PAT: /* Pattern modifier */+ case MOD_PATP: /* Allowed for Perl test */+ if (pctl != NULL) field = pctl;+ break;++ case MOD_PD: /* Pattern or data line modifier */+ case MOD_PDP: /* Ditto, allowed for Perl test */+ case MOD_PND: /* Ditto, but not default pattern */+ case MOD_PNDP: /* Ditto, allowed for Perl test */+ if (dctl != NULL) field = dctl;+ else if (pctl != NULL && (m->which == MOD_PD || m->which == MOD_PDP ||+ ctx != CTX_DEFPAT))+ field = pctl;+ break;+ }++if (field == NULL)+ {+ if (c == 0)+ fprintf(outfile, "** '%s' is not valid here\n", m->name);+ else+ fprintf(outfile, "** /%c is not valid here\n", c);+ return NULL;+ }++return (char *)field + offset;+}++++/*************************************************+* Decode a modifier list *+*************************************************/++/* A pointer to a control block is NULL when called in cases when that block is+not relevant. They are never all relevant in one call. At least one of patctl+and datctl is NULL. The second argument specifies which context to use for+modifiers that apply to contexts.++Arguments:+ p point to modifier string+ ctx CTX_PAT => pattern context+ CTX_POPPAT => pattern context for popped pattern+ CTX_DEFPAT => default pattern context+ CTX_DAT => data context+ CTX_DEFDAT => default data context+ pctl point to pattern control block+ dctl point to data control block++Returns: TRUE if successful decode, FALSE otherwise+*/++static BOOL+decode_modifiers(uint8_t *p, int ctx, patctl *pctl, datctl *dctl)+{+uint8_t *ep, *pp;+long li;+unsigned long uli;+BOOL first = TRUE;++for (;;)+ {+ void *field;+ modstruct *m;+ BOOL off = FALSE;+ unsigned int i, len;+ int index;+ char *endptr;++ /* Skip white space and commas. */++ while (isspace(*p) || *p == ',') p++;+ if (*p == 0) break;++ /* Find the end of the item; lose trailing whitespace at end of line. */++ for (ep = p; *ep != 0 && *ep != ','; ep++);+ if (*ep == 0)+ {+ while (ep > p && isspace(ep[-1])) ep--;+ *ep = 0;+ }++ /* Remember if the first character is '-'. */++ if (*p == '-')+ {+ off = TRUE;+ p++;+ }++ /* Find the length of a full-length modifier name, and scan for it. */++ pp = p;+ while (pp < ep && *pp != '=') pp++;+ index = scan_modifiers(p, pp - p);++ /* If the first modifier is unrecognized, try to interpret it as a sequence+ of single-character abbreviated modifiers. None of these modifiers have any+ associated data. They just set options or control bits. */++ if (index < 0)+ {+ uint32_t cc;+ uint8_t *mp = p;++ if (!first)+ {+ fprintf(outfile, "** Unrecognized modifier '%.*s'\n", (int)(ep-p), p);+ if (ep - p == 1)+ fprintf(outfile, "** Single-character modifiers must come first\n");+ return FALSE;+ }++ for (cc = *p; cc != ',' && cc != '\n' && cc != 0; cc = *(++p))+ {+ for (i = 0; i < C1MODLISTCOUNT; i++)+ if (cc == c1modlist[i].onechar) break;++ if (i >= C1MODLISTCOUNT)+ {+ fprintf(outfile, "** Unrecognized modifier '%c' in '%.*s'\n",+ *p, (int)(ep-mp), mp);+ return FALSE;+ }++ if (c1modlist[i].index >= 0)+ {+ index = c1modlist[i].index;+ }++ else+ {+ index = scan_modifiers((uint8_t *)(c1modlist[i].fullname),+ strlen(c1modlist[i].fullname));+ if (index < 0)+ {+ fprintf(outfile, "** Internal error: single-character equivalent "+ "modifier '%s' not found\n", c1modlist[i].fullname);+ return FALSE;+ }+ c1modlist[i].index = index; /* Cache for next time */+ }++ field = check_modifier(modlist + index, ctx, pctl, dctl, *p);+ if (field == NULL) return FALSE;++ /* /x is a special case; a second appearance changes PCRE2_EXTENDED to+ PCRE2_EXTENDED_MORE. */++ if (cc == 'x' && (*((uint32_t *)field) & PCRE2_EXTENDED) != 0)+ {+ *((uint32_t *)field) &= ~PCRE2_EXTENDED;+ *((uint32_t *)field) |= PCRE2_EXTENDED_MORE;+ }+ else+ *((uint32_t *)field) |= modlist[index].value;+ }++ continue; /* With tne next (fullname) modifier */+ }++ /* We have a match on a full-name modifier. Check for the existence of data+ when needed. */++ m = modlist + index; /* Save typing */+ if (m->type != MOD_CTL && m->type != MOD_OPT &&+ (m->type != MOD_IND || *pp == '='))+ {+ if (*pp++ != '=')+ {+ fprintf(outfile, "** '=' expected after '%s'\n", m->name);+ return FALSE;+ }+ if (off)+ {+ fprintf(outfile, "** '-' is not valid for '%s'\n", m->name);+ return FALSE;+ }+ }++ /* These on/off types have no data. */++ else if (*pp != ',' && *pp != '\n' && *pp != ' ' && *pp != 0)+ {+ fprintf(outfile, "** Unrecognized modifier '%.*s'\n", (int)(ep-p), p);+ return FALSE;+ }++ /* Set the data length for those types that have data. Then find the field+ that is to be set. If check_modifier() returns NULL, it has already output an+ error message. */++ len = ep - pp;+ field = check_modifier(m, ctx, pctl, dctl, 0);+ if (field == NULL) return FALSE;++ /* Process according to data type. */++ switch (m->type)+ {+ case MOD_CTL:+ case MOD_OPT:+ if (off) *((uint32_t *)field) &= ~m->value;+ else *((uint32_t *)field) |= m->value;+ break;++ case MOD_BSR:+ if (len == 7 && strncmpic(pp, (const uint8_t *)"default", 7) == 0)+ {+#ifdef BSR_ANYCRLF+ *((uint16_t *)field) = PCRE2_BSR_ANYCRLF;+#else+ *((uint16_t *)field) = PCRE2_BSR_UNICODE;+#endif+ if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 &= ~CTL2_BSR_SET;+ else dctl->control2 &= ~CTL2_BSR_SET;+ }+ else+ {+ if (len == 7 && strncmpic(pp, (const uint8_t *)"anycrlf", 7) == 0)+ *((uint16_t *)field) = PCRE2_BSR_ANYCRLF;+ else if (len == 7 && strncmpic(pp, (const uint8_t *)"unicode", 7) == 0)+ *((uint16_t *)field) = PCRE2_BSR_UNICODE;+ else goto INVALID_VALUE;+ if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 |= CTL2_BSR_SET;+ else dctl->control2 |= CTL2_BSR_SET;+ }+ pp = ep;+ break;++ case MOD_CHR: /* A single character */+ *((uint32_t *)field) = *pp++;+ break;++ case MOD_CON: /* A convert type/options list */+ for (;; pp++)+ {+ uint8_t *colon = (uint8_t *)strchr((const char *)pp, ':');+ len = ((colon != NULL && colon < ep)? colon:ep) - pp;+ for (i = 0; i < convertlistcount; i++)+ {+ if (strncmpic(pp, (const uint8_t *)convertlist[i].name, len) == 0)+ {+ if (*((uint32_t *)field) == CONVERT_UNSET)+ *((uint32_t *)field) = convertlist[i].option;+ else+ *((uint32_t *)field) |= convertlist[i].option;+ break;+ }+ }+ if (i >= convertlistcount) goto INVALID_VALUE;+ pp += len;+ if (*pp != ':') break;+ }+ break;++ case MOD_IN2: /* One or two unsigned integers */+ if (!isdigit(*pp)) goto INVALID_VALUE;+ uli = strtoul((const char *)pp, &endptr, 10);+ if (U32OVERFLOW(uli)) goto INVALID_VALUE;+ ((uint32_t *)field)[0] = (uint32_t)uli;+ if (*endptr == ':')+ {+ uli = strtoul((const char *)endptr+1, &endptr, 10);+ if (U32OVERFLOW(uli)) goto INVALID_VALUE;+ ((uint32_t *)field)[1] = (uint32_t)uli;+ }+ else ((uint32_t *)field)[1] = 0;+ pp = (uint8_t *)endptr;+ break;++ /* PCRE2_SIZE_MAX is usually SIZE_MAX, which may be greater, equal to, or+ less than ULONG_MAX. So first test for overflowing the long int, and then+ test for overflowing PCRE2_SIZE_MAX if it is smaller than ULONG_MAX. */++ case MOD_SIZ: /* PCRE2_SIZE value */+ if (!isdigit(*pp)) goto INVALID_VALUE;+ uli = strtoul((const char *)pp, &endptr, 10);+ if (uli == ULONG_MAX) goto INVALID_VALUE;+#if ULONG_MAX > PCRE2_SIZE_MAX+ if (uli > PCRE2_SIZE_MAX) goto INVALID_VALUE;+#endif+ *((PCRE2_SIZE *)field) = (PCRE2_SIZE)uli;+ pp = (uint8_t *)endptr;+ break;++ case MOD_IND: /* Unsigned integer with default */+ if (len == 0)+ {+ *((uint32_t *)field) = (uint32_t)(m->value);+ break;+ }+ /* Fall through */++ case MOD_INT: /* Unsigned integer */+ if (!isdigit(*pp)) goto INVALID_VALUE;+ uli = strtoul((const char *)pp, &endptr, 10);+ if (U32OVERFLOW(uli)) goto INVALID_VALUE;+ *((uint32_t *)field) = (uint32_t)uli;+ pp = (uint8_t *)endptr;+ break;++ case MOD_INS: /* Signed integer */+ if (!isdigit(*pp) && *pp != '-') goto INVALID_VALUE;+ li = strtol((const char *)pp, &endptr, 10);+ if (S32OVERFLOW(li)) goto INVALID_VALUE;+ *((int32_t *)field) = (int32_t)li;+ pp = (uint8_t *)endptr;+ break;++ case MOD_NL:+ for (i = 0; i < sizeof(newlines)/sizeof(char *); i++)+ if (len == strlen(newlines[i]) &&+ strncmpic(pp, (const uint8_t *)newlines[i], len) == 0) break;+ if (i >= sizeof(newlines)/sizeof(char *)) goto INVALID_VALUE;+ if (i == 0)+ {+ *((uint16_t *)field) = NEWLINE_DEFAULT;+ if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 &= ~CTL2_NL_SET;+ else dctl->control2 &= ~CTL2_NL_SET;+ }+ else+ {+ *((uint16_t *)field) = i;+ if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 |= CTL2_NL_SET;+ else dctl->control2 |= CTL2_NL_SET;+ }+ pp = ep;+ break;++ case MOD_NN: /* Name or (signed) number; may be several */+ if (isdigit(*pp) || *pp == '-')+ {+ int ct = MAXCPYGET - 1;+ int32_t value;+ li = strtol((const char *)pp, &endptr, 10);+ if (S32OVERFLOW(li)) goto INVALID_VALUE;+ value = (int32_t)li;+ field = (char *)field - m->offset + m->value; /* Adjust field ptr */+ if (value >= 0) /* Add new number */+ {+ while (*((int32_t *)field) >= 0 && ct-- > 0) /* Skip previous */+ field = (char *)field + sizeof(int32_t);+ if (ct <= 0)+ {+ fprintf(outfile, "** Too many numeric '%s' modifiers\n", m->name);+ return FALSE;+ }+ }+ *((int32_t *)field) = value;+ if (ct > 0) ((int32_t *)field)[1] = -1;+ pp = (uint8_t *)endptr;+ }++ /* Multiple strings are put end to end. */++ else+ {+ char *nn = (char *)field;+ if (len > 0) /* Add new name */+ {+ if (len > MAX_NAME_SIZE)+ {+ fprintf(outfile, "** Group name in '%s' is too long\n", m->name);+ return FALSE;+ }+ while (*nn != 0) nn += strlen(nn) + 1;+ if (nn + len + 2 - (char *)field > LENCPYGET)+ {+ fprintf(outfile, "** Too many characters in named '%s' modifiers\n",+ m->name);+ return FALSE;+ }+ memcpy(nn, pp, len);+ }+ nn[len] = 0 ;+ nn[len+1] = 0;+ pp = ep;+ }+ break;++ case MOD_STR:+ if (len + 1 > m->value)+ {+ fprintf(outfile, "** Overlong value for '%s' (max %d code units)\n",+ m->name, m->value - 1);+ return FALSE;+ }+ memcpy(field, pp, len);+ ((uint8_t *)field)[len] = 0;+ pp = ep;+ break;+ }++ if (*pp != ',' && *pp != '\n' && *pp != ' ' && *pp != 0)+ {+ fprintf(outfile, "** Comma expected after modifier item '%s'\n", m->name);+ return FALSE;+ }++ p = pp;+ first = FALSE;++ if (ctx == CTX_POPPAT &&+ (pctl->options != 0 ||+ pctl->tables_id != 0 ||+ pctl->locale[0] != 0 ||+ (pctl->control & NOTPOP_CONTROLS) != 0))+ {+ fprintf(outfile, "** '%s' is not valid here\n", m->name);+ return FALSE;+ }+ }++return TRUE;++INVALID_VALUE:+fprintf(outfile, "** Invalid value in '%.*s'\n", (int)(ep-p), p);+return FALSE;+}+++/*************************************************+* Get info from a pattern *+*************************************************/++/* A wrapped call to pcre2_pattern_info(), applied to the current compiled+pattern.++Arguments:+ what code for the required information+ where where to put the answer+ unsetok PCRE2_ERROR_UNSET is an "expected" result++Returns: the return from pcre2_pattern_info()+*/++static int+pattern_info(int what, void *where, BOOL unsetok)+{+int rc;+PCRE2_PATTERN_INFO(rc, compiled_code, what, NULL); /* Exercise the code */+PCRE2_PATTERN_INFO(rc, compiled_code, what, where);+if (rc >= 0) return 0;+if (rc != PCRE2_ERROR_UNSET || !unsetok)+ {+ fprintf(outfile, "Error %d from pcre2_pattern_info_%d(%d)\n", rc, test_mode,+ what);+ if (rc == PCRE2_ERROR_BADMODE)+ fprintf(outfile, "Running in %d-bit mode but pattern was compiled in "+ "%d-bit mode\n", test_mode,+ 8 * (FLD(compiled_code, flags) & PCRE2_MODE_MASK));+ }+return rc;+}++++#ifdef SUPPORT_PCRE2_8+/*************************************************+* Show something in a list *+*************************************************/++/* This function just helps to keep the code that uses it tidier. It's used for+various lists of things where there needs to be introductory text before the+first item. As these calls are all in the POSIX-support code, they happen only+when 8-bit mode is supported. */++static void+prmsg(const char **msg, const char *s)+{+fprintf(outfile, "%s %s", *msg, s);+*msg = "";+}+#endif /* SUPPORT_PCRE2_8 */++++/*************************************************+* Show control bits *+*************************************************/++/* Called for mutually exclusive controls and for unsupported POSIX controls.+Because the bits are unique, this can be used for both pattern and data control+words.++Arguments:+ controls control bits+ controls2 more control bits+ before text to print before++Returns: nothing+*/++static void+show_controls(uint32_t controls, uint32_t controls2, const char *before)+{+fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",+ before,+ ((controls & CTL_AFTERTEXT) != 0)? " aftertext" : "",+ ((controls & CTL_ALLAFTERTEXT) != 0)? " allaftertext" : "",+ ((controls & CTL_ALLCAPTURES) != 0)? " allcaptures" : "",+ ((controls & CTL_ALLUSEDTEXT) != 0)? " allusedtext" : "",+ ((controls2 & CTL2_ALLVECTOR) != 0)? " allvector" : "",+ ((controls & CTL_ALTGLOBAL) != 0)? " altglobal" : "",+ ((controls & CTL_BINCODE) != 0)? " bincode" : "",+ ((controls2 & CTL2_BSR_SET) != 0)? " bsr" : "",+ ((controls & CTL_CALLOUT_CAPTURE) != 0)? " callout_capture" : "",+ ((controls2 & CTL2_CALLOUT_EXTRA) != 0)? " callout_extra" : "",+ ((controls & CTL_CALLOUT_INFO) != 0)? " callout_info" : "",+ ((controls & CTL_CALLOUT_NONE) != 0)? " callout_none" : "",+ ((controls2 & CTL2_CALLOUT_NO_WHERE) != 0)? " callout_no_where" : "",+ ((controls & CTL_DFA) != 0)? " dfa" : "",+ ((controls & CTL_EXPAND) != 0)? " expand" : "",+ ((controls & CTL_FINDLIMITS) != 0)? " find_limits" : "",+ ((controls & CTL_FRAMESIZE) != 0)? " framesize" : "",+ ((controls & CTL_FULLBINCODE) != 0)? " fullbincode" : "",+ ((controls & CTL_GETALL) != 0)? " getall" : "",+ ((controls & CTL_GLOBAL) != 0)? " global" : "",+ ((controls & CTL_HEXPAT) != 0)? " hex" : "",+ ((controls & CTL_INFO) != 0)? " info" : "",+ ((controls & CTL_JITFAST) != 0)? " jitfast" : "",+ ((controls & CTL_JITVERIFY) != 0)? " jitverify" : "",+ ((controls & CTL_MARK) != 0)? " mark" : "",+ ((controls & CTL_MEMORY) != 0)? " memory" : "",+ ((controls2 & CTL2_NL_SET) != 0)? " newline" : "",+ ((controls & CTL_NULLCONTEXT) != 0)? " null_context" : "",+ ((controls & CTL_POSIX) != 0)? " posix" : "",+ ((controls & CTL_POSIX_NOSUB) != 0)? " posix_nosub" : "",+ ((controls & CTL_PUSH) != 0)? " push" : "",+ ((controls & CTL_PUSHCOPY) != 0)? " pushcopy" : "",+ ((controls & CTL_PUSHTABLESCOPY) != 0)? " pushtablescopy" : "",+ ((controls & CTL_STARTCHAR) != 0)? " startchar" : "",+ ((controls2 & CTL2_SUBSTITUTE_CALLOUT) != 0)? " substitute_callout" : "",+ ((controls2 & CTL2_SUBSTITUTE_EXTENDED) != 0)? " substitute_extended" : "",+ ((controls2 & CTL2_SUBSTITUTE_LITERAL) != 0)? " substitute_literal" : "",+ ((controls2 & CTL2_SUBSTITUTE_MATCHED) != 0)? " substitute_matched" : "",+ ((controls2 & CTL2_SUBSTITUTE_OVERFLOW_LENGTH) != 0)? " substitute_overflow_length" : "",+ ((controls2 & CTL2_SUBSTITUTE_REPLACEMENT_ONLY) != 0)? " substitute_replacement_only" : "",+ ((controls2 & CTL2_SUBSTITUTE_UNKNOWN_UNSET) != 0)? " substitute_unknown_unset" : "",+ ((controls2 & CTL2_SUBSTITUTE_UNSET_EMPTY) != 0)? " substitute_unset_empty" : "",+ ((controls & CTL_USE_LENGTH) != 0)? " use_length" : "",+ ((controls & CTL_UTF8_INPUT) != 0)? " utf8_input" : "",+ ((controls & CTL_ZERO_TERMINATE) != 0)? " zero_terminate" : "");+}++++/*************************************************+* Show compile options *+*************************************************/++/* Called from show_pattern_info() and for unsupported POSIX options.++Arguments:+ options an options word+ before text to print before+ after text to print after++Returns: nothing+*/++static void+show_compile_options(uint32_t options, const char *before, const char *after)+{+if (options == 0) fprintf(outfile, "%s <none>%s", before, after);+else fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",+ before,+ ((options & PCRE2_ALT_BSUX) != 0)? " alt_bsux" : "",+ ((options & PCRE2_ALT_CIRCUMFLEX) != 0)? " alt_circumflex" : "",+ ((options & PCRE2_ALT_VERBNAMES) != 0)? " alt_verbnames" : "",+ ((options & PCRE2_ALLOW_EMPTY_CLASS) != 0)? " allow_empty_class" : "",+ ((options & PCRE2_ANCHORED) != 0)? " anchored" : "",+ ((options & PCRE2_AUTO_CALLOUT) != 0)? " auto_callout" : "",+ ((options & PCRE2_CASELESS) != 0)? " caseless" : "",+ ((options & PCRE2_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",+ ((options & PCRE2_DOTALL) != 0)? " dotall" : "",+ ((options & PCRE2_DUPNAMES) != 0)? " dupnames" : "",+ ((options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",+ ((options & PCRE2_EXTENDED) != 0)? " extended" : "",+ ((options & PCRE2_EXTENDED_MORE) != 0)? " extended_more" : "",+ ((options & PCRE2_FIRSTLINE) != 0)? " firstline" : "",+ ((options & PCRE2_LITERAL) != 0)? " literal" : "",+ ((options & PCRE2_MATCH_INVALID_UTF) != 0)? " match_invalid_utf" : "",+ ((options & PCRE2_MATCH_UNSET_BACKREF) != 0)? " match_unset_backref" : "",+ ((options & PCRE2_MULTILINE) != 0)? " multiline" : "",+ ((options & PCRE2_NEVER_BACKSLASH_C) != 0)? " never_backslash_c" : "",+ ((options & PCRE2_NEVER_UCP) != 0)? " never_ucp" : "",+ ((options & PCRE2_NEVER_UTF) != 0)? " never_utf" : "",+ ((options & PCRE2_NO_AUTO_CAPTURE) != 0)? " no_auto_capture" : "",+ ((options & PCRE2_NO_AUTO_POSSESS) != 0)? " no_auto_possess" : "",+ ((options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)? " no_dotstar_anchor" : "",+ ((options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",+ ((options & PCRE2_NO_START_OPTIMIZE) != 0)? " no_start_optimize" : "",+ ((options & PCRE2_UCP) != 0)? " ucp" : "",+ ((options & PCRE2_UNGREEDY) != 0)? " ungreedy" : "",+ ((options & PCRE2_USE_OFFSET_LIMIT) != 0)? " use_offset_limit" : "",+ ((options & PCRE2_UTF) != 0)? " utf" : "",+ after);+}+++/*************************************************+* Show compile extra options *+*************************************************/++/* Called from show_pattern_info() and for unsupported POSIX options.++Arguments:+ options an options word+ before text to print before+ after text to print after++Returns: nothing+*/++static void+show_compile_extra_options(uint32_t options, const char *before,+ const char *after)+{+if (options == 0) fprintf(outfile, "%s <none>%s", before, after);+else fprintf(outfile, "%s%s%s%s%s%s%s%s",+ before,+ ((options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) != 0)? " allow_surrogate_escapes" : "",+ ((options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) != 0)? " bad_escape_is_literal" : "",+ ((options & PCRE2_EXTRA_ALT_BSUX) != 0)? " extra_alt_bsux" : "",+ ((options & PCRE2_EXTRA_MATCH_WORD) != 0)? " match_word" : "",+ ((options & PCRE2_EXTRA_MATCH_LINE) != 0)? " match_line" : "",+ ((options & PCRE2_EXTRA_ESCAPED_CR_IS_LF) != 0)? " escaped_cr_is_lf" : "",+ after);+}++++#ifdef SUPPORT_PCRE2_8+/*************************************************+* Show match options *+*************************************************/++/* Called for unsupported POSIX options. */++static void+show_match_options(uint32_t options)+{+fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s",+ ((options & PCRE2_ANCHORED) != 0)? " anchored" : "",+ ((options & PCRE2_COPY_MATCHED_SUBJECT) != 0)? " copy_matched_subject" : "",+ ((options & PCRE2_DFA_RESTART) != 0)? " dfa_restart" : "",+ ((options & PCRE2_DFA_SHORTEST) != 0)? " dfa_shortest" : "",+ ((options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",+ ((options & PCRE2_NO_JIT) != 0)? " no_jit" : "",+ ((options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",+ ((options & PCRE2_NOTBOL) != 0)? " notbol" : "",+ ((options & PCRE2_NOTEMPTY) != 0)? " notempty" : "",+ ((options & PCRE2_NOTEMPTY_ATSTART) != 0)? " notempty_atstart" : "",+ ((options & PCRE2_NOTEOL) != 0)? " noteol" : "",+ ((options & PCRE2_PARTIAL_HARD) != 0)? " partial_hard" : "",+ ((options & PCRE2_PARTIAL_SOFT) != 0)? " partial_soft" : "");+}+#endif /* SUPPORT_PCRE2_8 */++++/*************************************************+* Show memory usage info for a pattern *+*************************************************/++static void+show_memory_info(void)+{+uint32_t name_count, name_entry_size;+size_t size, cblock_size;++/* One of the test_mode values will always be true, but to stop a compiler+warning we must initialize cblock_size. */++cblock_size = 0;+#ifdef SUPPORT_PCRE2_8+if (test_mode == PCRE8_MODE) cblock_size = sizeof(pcre2_real_code_8);+#endif+#ifdef SUPPORT_PCRE2_16+if (test_mode == PCRE16_MODE) cblock_size = sizeof(pcre2_real_code_16);+#endif+#ifdef SUPPORT_PCRE2_32+if (test_mode == PCRE32_MODE) cblock_size = sizeof(pcre2_real_code_32);+#endif++(void)pattern_info(PCRE2_INFO_SIZE, &size, FALSE);+(void)pattern_info(PCRE2_INFO_NAMECOUNT, &name_count, FALSE);+(void)pattern_info(PCRE2_INFO_NAMEENTRYSIZE, &name_entry_size, FALSE);+fprintf(outfile, "Memory allocation (code space): %d\n",+ (int)(size - name_count*name_entry_size*code_unit_size - cblock_size));+if (pat_patctl.jit != 0)+ {+ (void)pattern_info(PCRE2_INFO_JITSIZE, &size, FALSE);+ fprintf(outfile, "Memory allocation (JIT code): %d\n", (int)size);+ }+}++++/*************************************************+* Show frame size info for a pattern *+*************************************************/++static void+show_framesize(void)+{+size_t frame_size;+(void)pattern_info(PCRE2_INFO_FRAMESIZE, &frame_size, FALSE);+fprintf(outfile, "Frame size for pcre2_match(): %d\n", (int)frame_size);+}++++/*************************************************+* Get and output an error message *+*************************************************/++static BOOL+print_error_message(int errorcode, const char *before, const char *after)+{+int len;+PCRE2_GET_ERROR_MESSAGE(len, errorcode, pbuffer);+if (len < 0)+ {+ fprintf(outfile, "\n** pcre2test internal error: cannot interpret error "+ "number\n** Unexpected return (%d) from pcre2_get_error_message()\n", len);+ }+else+ {+ fprintf(outfile, "%s", before);+ PCHARSV(CASTVAR(void *, pbuffer), 0, len, FALSE, outfile);+ fprintf(outfile, "%s", after);+ }+return len >= 0;+}+++/*************************************************+* Callback function for callout enumeration *+*************************************************/++/* The only differences in the callout emumeration block for different code+unit widths are that the pointers to the subject, the most recent MARK, and a+callout argument string point to strings of the appropriate width. Casts can be+used to deal with this.++Argument:+ cb pointer to enumerate block+ callout_data user data++Returns: 0+*/++static int callout_callback(pcre2_callout_enumerate_block_8 *cb,+ void *callout_data)+{+uint32_t i;+BOOL utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;++(void)callout_data; /* Not currently displayed */++fprintf(outfile, "Callout ");+if (cb->callout_string != NULL)+ {+ uint32_t delimiter = CODE_UNIT(cb->callout_string, -1);+ fprintf(outfile, "%c", delimiter);+ PCHARSV(cb->callout_string, 0,+ cb->callout_string_length, utf, outfile);+ for (i = 0; callout_start_delims[i] != 0; i++)+ if (delimiter == callout_start_delims[i])+ {+ delimiter = callout_end_delims[i];+ break;+ }+ fprintf(outfile, "%c ", delimiter);+ }+else fprintf(outfile, "%d ", cb->callout_number);++fprintf(outfile, "%.*s\n",+ (int)((cb->next_item_length == 0)? 1 : cb->next_item_length),+ pbuffer8 + cb->pattern_position);++return 0;+}++++/*************************************************+* Show information about a pattern *+*************************************************/++/* This function is called after a pattern has been compiled if any of the+information-requesting controls have been set.++Arguments: none++Returns: PR_OK continue processing next line+ PR_SKIP skip to a blank line+ PR_ABEND abort the pcre2test run+*/++static int+show_pattern_info(void)+{+uint32_t compile_options, overall_options, extra_options;+BOOL utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;++if ((pat_patctl.control & (CTL_BINCODE|CTL_FULLBINCODE)) != 0)+ {+ fprintf(outfile, "------------------------------------------------------------------\n");+ PCRE2_PRINTINT((pat_patctl.control & CTL_FULLBINCODE) != 0);+ }++if ((pat_patctl.control & CTL_INFO) != 0)+ {+ int rc;+ void *nametable;+ uint8_t *start_bits;+ BOOL heap_limit_set, match_limit_set, depth_limit_set;+ uint32_t backrefmax, bsr_convention, capture_count, first_ctype, first_cunit,+ hasbackslashc, hascrorlf, jchanged, last_ctype, last_cunit, match_empty,+ depth_limit, heap_limit, match_limit, minlength, nameentrysize, namecount,+ newline_convention;++ /* Exercise the error route. */++ PCRE2_PATTERN_INFO(rc, compiled_code, 999, NULL);+ (void)rc;++ /* These info requests may return PCRE2_ERROR_UNSET. */++ switch(pattern_info(PCRE2_INFO_HEAPLIMIT, &heap_limit, TRUE))+ {+ case 0:+ heap_limit_set = TRUE;+ break;++ case PCRE2_ERROR_UNSET:+ heap_limit_set = FALSE;+ break;++ default:+ return PR_ABEND;+ }++ switch(pattern_info(PCRE2_INFO_MATCHLIMIT, &match_limit, TRUE))+ {+ case 0:+ match_limit_set = TRUE;+ break;++ case PCRE2_ERROR_UNSET:+ match_limit_set = FALSE;+ break;++ default:+ return PR_ABEND;+ }++ switch(pattern_info(PCRE2_INFO_DEPTHLIMIT, &depth_limit, TRUE))+ {+ case 0:+ depth_limit_set = TRUE;+ break;++ case PCRE2_ERROR_UNSET:+ depth_limit_set = FALSE;+ break;++ default:+ return PR_ABEND;+ }++ /* These info requests should always succeed. */++ if (pattern_info(PCRE2_INFO_BACKREFMAX, &backrefmax, FALSE) ++ pattern_info(PCRE2_INFO_BSR, &bsr_convention, FALSE) ++ pattern_info(PCRE2_INFO_CAPTURECOUNT, &capture_count, FALSE) ++ pattern_info(PCRE2_INFO_FIRSTBITMAP, &start_bits, FALSE) ++ pattern_info(PCRE2_INFO_FIRSTCODEUNIT, &first_cunit, FALSE) ++ pattern_info(PCRE2_INFO_FIRSTCODETYPE, &first_ctype, FALSE) ++ pattern_info(PCRE2_INFO_HASBACKSLASHC, &hasbackslashc, FALSE) ++ pattern_info(PCRE2_INFO_HASCRORLF, &hascrorlf, FALSE) ++ pattern_info(PCRE2_INFO_JCHANGED, &jchanged, FALSE) ++ pattern_info(PCRE2_INFO_LASTCODEUNIT, &last_cunit, FALSE) ++ pattern_info(PCRE2_INFO_LASTCODETYPE, &last_ctype, FALSE) ++ pattern_info(PCRE2_INFO_MATCHEMPTY, &match_empty, FALSE) ++ pattern_info(PCRE2_INFO_MINLENGTH, &minlength, FALSE) ++ pattern_info(PCRE2_INFO_NAMECOUNT, &namecount, FALSE) ++ pattern_info(PCRE2_INFO_NAMEENTRYSIZE, &nameentrysize, FALSE) ++ pattern_info(PCRE2_INFO_NAMETABLE, &nametable, FALSE) ++ pattern_info(PCRE2_INFO_NEWLINE, &newline_convention, FALSE)+ != 0)+ return PR_ABEND;++ fprintf(outfile, "Capture group count = %d\n", capture_count);++ if (backrefmax > 0)+ fprintf(outfile, "Max back reference = %d\n", backrefmax);++ if (maxlookbehind > 0)+ fprintf(outfile, "Max lookbehind = %d\n", maxlookbehind);++ if (heap_limit_set)+ fprintf(outfile, "Heap limit = %u\n", heap_limit);++ if (match_limit_set)+ fprintf(outfile, "Match limit = %u\n", match_limit);++ if (depth_limit_set)+ fprintf(outfile, "Depth limit = %u\n", depth_limit);++ if (namecount > 0)+ {+ fprintf(outfile, "Named capture groups:\n");+ for (; namecount > 0; namecount--)+ {+ int imm2_size = test_mode == PCRE8_MODE ? 2 : 1;+ uint32_t length = (uint32_t)STRLEN(nametable + imm2_size);+ fprintf(outfile, " ");++ /* In UTF mode the name may be a UTF string containing non-ASCII+ letters and digits. We must output it as a UTF-8 string. In non-UTF mode,+ use the normal string printing functions, which use escapes for all+ non-ASCII characters. */++ if (utf)+ {+#ifdef SUPPORT_PCRE2_32+ if (test_mode == PCRE32_MODE)+ {+ PCRE2_SPTR32 nameptr = (PCRE2_SPTR32)nametable + imm2_size;+ while (*nameptr != 0)+ {+ uint8_t u8buff[6];+ int len = ord2utf8(*nameptr++, u8buff);+ fprintf(outfile, "%.*s", len, u8buff);+ }+ }+#endif+#ifdef SUPPORT_PCRE2_16+ if (test_mode == PCRE16_MODE)+ {+ PCRE2_SPTR16 nameptr = (PCRE2_SPTR16)nametable + imm2_size;+ while (*nameptr != 0)+ {+ int len;+ uint8_t u8buff[6];+ uint32_t c = *nameptr++ & 0xffff;+ if (c >= 0xD800 && c < 0xDC00)+ c = ((c & 0x3ff) << 10) + (*nameptr++ & 0x3ff) + 0x10000;+ len = ord2utf8(c, u8buff);+ fprintf(outfile, "%.*s", len, u8buff);+ }+ }+#endif+#ifdef SUPPORT_PCRE2_8+ if (test_mode == PCRE8_MODE)+ fprintf(outfile, "%s", (PCRE2_SPTR8)nametable + imm2_size);+#endif+ }+ else /* Not UTF mode */+ {+ PCHARSV(nametable, imm2_size, length, FALSE, outfile);+ }++ while (length++ < nameentrysize - imm2_size) putc(' ', outfile);++#ifdef SUPPORT_PCRE2_32+ if (test_mode == PCRE32_MODE)+ fprintf(outfile, "%3d\n", (int)(((PCRE2_SPTR32)nametable)[0]));+#endif+#ifdef SUPPORT_PCRE2_16+ if (test_mode == PCRE16_MODE)+ fprintf(outfile, "%3d\n", (int)(((PCRE2_SPTR16)nametable)[0]));+#endif+#ifdef SUPPORT_PCRE2_8+ if (test_mode == PCRE8_MODE)+ fprintf(outfile, "%3d\n", (int)(+ ((((PCRE2_SPTR8)nametable)[0]) << 8) | ((PCRE2_SPTR8)nametable)[1]));+#endif++ nametable = (void*)((PCRE2_SPTR8)nametable + nameentrysize * code_unit_size);+ }+ }++ if (hascrorlf) fprintf(outfile, "Contains explicit CR or LF match\n");+ if (hasbackslashc) fprintf(outfile, "Contains \\C\n");+ if (match_empty) fprintf(outfile, "May match empty string\n");++ pattern_info(PCRE2_INFO_ARGOPTIONS, &compile_options, FALSE);+ pattern_info(PCRE2_INFO_ALLOPTIONS, &overall_options, FALSE);+ pattern_info(PCRE2_INFO_EXTRAOPTIONS, &extra_options, FALSE);++ /* Remove UTF/UCP if they were there only because of forbid_utf. This saves+ cluttering up the verification output of non-UTF test files. */++ if ((pat_patctl.options & PCRE2_NEVER_UTF) == 0)+ {+ compile_options &= ~PCRE2_NEVER_UTF;+ overall_options &= ~PCRE2_NEVER_UTF;+ }++ if ((pat_patctl.options & PCRE2_NEVER_UCP) == 0)+ {+ compile_options &= ~PCRE2_NEVER_UCP;+ overall_options &= ~PCRE2_NEVER_UCP;+ }++ if ((compile_options|overall_options) != 0)+ {+ if (compile_options == overall_options)+ show_compile_options(compile_options, "Options:", "\n");+ else+ {+ show_compile_options(compile_options, "Compile options:", "\n");+ show_compile_options(overall_options, "Overall options:", "\n");+ }+ }++ if (extra_options != 0)+ show_compile_extra_options(extra_options, "Extra options:", "\n");++ if (jchanged) fprintf(outfile, "Duplicate name status changes\n");++ if ((pat_patctl.control2 & CTL2_BSR_SET) != 0 ||+ (FLD(compiled_code, flags) & PCRE2_BSR_SET) != 0)+ fprintf(outfile, "\\R matches %s\n", (bsr_convention == PCRE2_BSR_UNICODE)?+ "any Unicode newline" : "CR, LF, or CRLF");++ if ((FLD(compiled_code, flags) & PCRE2_NL_SET) != 0)+ {+ switch (newline_convention)+ {+ case PCRE2_NEWLINE_CR:+ fprintf(outfile, "Forced newline is CR\n");+ break;++ case PCRE2_NEWLINE_LF:+ fprintf(outfile, "Forced newline is LF\n");+ break;++ case PCRE2_NEWLINE_CRLF:+ fprintf(outfile, "Forced newline is CRLF\n");+ break;++ case PCRE2_NEWLINE_ANYCRLF:+ fprintf(outfile, "Forced newline is CR, LF, or CRLF\n");+ break;++ case PCRE2_NEWLINE_ANY:+ fprintf(outfile, "Forced newline is any Unicode newline\n");+ break;++ case PCRE2_NEWLINE_NUL:+ fprintf(outfile, "Forced newline is NUL\n");+ break;++ default:+ break;+ }+ }++ if (first_ctype == 2)+ {+ fprintf(outfile, "First code unit at start or follows newline\n");+ }+ else if (first_ctype == 1)+ {+ const char *caseless =+ ((FLD(compiled_code, flags) & PCRE2_FIRSTCASELESS) == 0)?+ "" : " (caseless)";+ if (PRINTOK(first_cunit))+ fprintf(outfile, "First code unit = \'%c\'%s\n", first_cunit, caseless);+ else+ {+ fprintf(outfile, "First code unit = ");+ pchar(first_cunit, FALSE, outfile);+ fprintf(outfile, "%s\n", caseless);+ }+ }+ else if (start_bits != NULL)+ {+ int i;+ int c = 24;+ fprintf(outfile, "Starting code units: ");+ for (i = 0; i < 256; i++)+ {+ if ((start_bits[i/8] & (1u << (i&7))) != 0)+ {+ if (c > 75)+ {+ fprintf(outfile, "\n ");+ c = 2;+ }+ if (PRINTOK(i) && i != ' ')+ {+ fprintf(outfile, "%c ", i);+ c += 2;+ }+ else+ {+ fprintf(outfile, "\\x%02x ", i);+ c += 5;+ }+ }+ }+ fprintf(outfile, "\n");+ }++ if (last_ctype != 0)+ {+ const char *caseless =+ ((FLD(compiled_code, flags) & PCRE2_LASTCASELESS) == 0)?+ "" : " (caseless)";+ if (PRINTOK(last_cunit))+ fprintf(outfile, "Last code unit = \'%c\'%s\n", last_cunit, caseless);+ else+ {+ fprintf(outfile, "Last code unit = ");+ pchar(last_cunit, FALSE, outfile);+ fprintf(outfile, "%s\n", caseless);+ }+ }++ if ((FLD(compiled_code, overall_options) & PCRE2_NO_START_OPTIMIZE) == 0)+ fprintf(outfile, "Subject length lower bound = %d\n", minlength);++ if (pat_patctl.jit != 0 && (pat_patctl.control & CTL_JITVERIFY) != 0)+ {+ if (FLD(compiled_code, executable_jit) != NULL)+ fprintf(outfile, "JIT compilation was successful\n");+ else+ {+#ifdef SUPPORT_JIT+ fprintf(outfile, "JIT compilation was not successful");+ if (jitrc != 0 && !print_error_message(jitrc, " (", ")"))+ return PR_ABEND;+ fprintf(outfile, "\n");+#else+ fprintf(outfile, "JIT support is not available in this version of PCRE2\n");+#endif+ }+ }+ }++if ((pat_patctl.control & CTL_CALLOUT_INFO) != 0)+ {+ int errorcode;+ PCRE2_CALLOUT_ENUMERATE(errorcode, callout_callback, 0);+ if (errorcode != 0)+ {+ fprintf(outfile, "Callout enumerate failed: error %d: ", errorcode);+ if (errorcode < 0 && !print_error_message(errorcode, "", "\n"))+ return PR_ABEND;+ return PR_SKIP;+ }+ }++return PR_OK;+}++++/*************************************************+* Handle serialization error *+*************************************************/++/* Print an error message after a serialization failure.++Arguments:+ rc the error code+ msg an initial message for what failed++Returns: FALSE if print_error_message() fails+*/++static BOOL+serial_error(int rc, const char *msg)+{+fprintf(outfile, "%s failed: error %d: ", msg, rc);+return print_error_message(rc, "", "\n");+}++++/*************************************************+* Open file for save/load commands *+*************************************************/++/* This function decodes the file name and opens the file.++Arguments:+ buffptr point after the #command+ mode open mode+ fptr points to the FILE variable+ name name of # command++Returns: PR_OK or PR_ABEND+*/++static int+open_file(uint8_t *buffptr, const char *mode, FILE **fptr, const char *name)+{+char *endf;+char *filename = (char *)buffptr;+while (isspace(*filename)) filename++;+endf = filename + strlen8(filename);+while (endf > filename && isspace(endf[-1])) endf--;++if (endf == filename)+ {+ fprintf(outfile, "** File name expected after %s\n", name);+ return PR_ABEND;+ }++*endf = 0;+*fptr = fopen((const char *)filename, mode);+if (*fptr == NULL)+ {+ fprintf(outfile, "** Failed to open '%s': %s\n", filename, strerror(errno));+ return PR_ABEND;+ }++return PR_OK;+}++++/*************************************************+* Process command line *+*************************************************/++/* This function is called for lines beginning with # and a character that is+not ! or whitespace, when encountered between tests, which means that there is+no compiled pattern (compiled_code is NULL). The line is in buffer.++Arguments: none++Returns: PR_OK continue processing next line+ PR_SKIP skip to a blank line+ PR_ABEND abort the pcre2test run+*/++static int+process_command(void)+{+FILE *f;+PCRE2_SIZE serial_size;+size_t i;+int rc, cmd, cmdlen, yield;+uint16_t first_listed_newline;+const char *cmdname;+uint8_t *argptr, *serial;++yield = PR_OK;+cmd = CMD_UNKNOWN;+cmdlen = 0;++for (i = 0; i < cmdlistcount; i++)+ {+ cmdname = cmdlist[i].name;+ cmdlen = strlen(cmdname);+ if (strncmp((char *)(buffer+1), cmdname, cmdlen) == 0 &&+ isspace(buffer[cmdlen+1]))+ {+ cmd = cmdlist[i].value;+ break;+ }+ }++argptr = buffer + cmdlen + 1;++if (restrict_for_perl_test && cmd != CMD_PATTERN && cmd != CMD_SUBJECT)+ {+ fprintf(outfile, "** #%s is not allowed after #perltest\n", cmdname);+ return PR_ABEND;+ }++switch(cmd)+ {+ case CMD_UNKNOWN:+ fprintf(outfile, "** Unknown command: %s", buffer);+ break;++ case CMD_FORBID_UTF:+ forbid_utf = PCRE2_NEVER_UTF|PCRE2_NEVER_UCP;+ break;++ case CMD_PERLTEST:+ restrict_for_perl_test = TRUE;+ break;++ /* Set default pattern modifiers */++ case CMD_PATTERN:+ (void)decode_modifiers(argptr, CTX_DEFPAT, &def_patctl, NULL);+ if (def_patctl.jit == 0 && (def_patctl.control & CTL_JITVERIFY) != 0)+ def_patctl.jit = JIT_DEFAULT;+ break;++ /* Set default subject modifiers */++ case CMD_SUBJECT:+ (void)decode_modifiers(argptr, CTX_DEFDAT, NULL, &def_datctl);+ break;++ /* Check the default newline, and if not one of those listed, set up the+ first one to be forced. An empty list unsets. */++ case CMD_NEWLINE_DEFAULT:+ local_newline_default = 0; /* Unset */+ first_listed_newline = 0;+ for (;;)+ {+ while (isspace(*argptr)) argptr++;+ if (*argptr == 0) break;+ for (i = 1; i < sizeof(newlines)/sizeof(char *); i++)+ {+ size_t nlen = strlen(newlines[i]);+ if (strncmpic(argptr, (const uint8_t *)newlines[i], nlen) == 0 &&+ isspace(argptr[nlen]))+ {+ if (i == NEWLINE_DEFAULT) return PR_OK; /* Default is valid */+ if (first_listed_newline == 0) first_listed_newline = i;+ }+ }+ while (*argptr != 0 && !isspace(*argptr)) argptr++;+ }+ local_newline_default = first_listed_newline;+ break;++ /* Pop or copy a compiled pattern off the stack. Modifiers that do not affect+ the compiled pattern (e.g. to give information) are permitted. The default+ pattern modifiers are ignored. */++ case CMD_POP:+ case CMD_POPCOPY:+ if (patstacknext <= 0)+ {+ fprintf(outfile, "** Can't pop off an empty stack\n");+ return PR_SKIP;+ }+ memset(&pat_patctl, 0, sizeof(patctl)); /* Completely unset */+ if (!decode_modifiers(argptr, CTX_POPPAT, &pat_patctl, NULL))+ return PR_SKIP;++ if (cmd == CMD_POP)+ {+ SET(compiled_code, patstack[--patstacknext]);+ }+ else+ {+ PCRE2_CODE_COPY_FROM_VOID(compiled_code, patstack[patstacknext - 1]);+ }++ if (pat_patctl.jit != 0)+ {+ PCRE2_JIT_COMPILE(jitrc, compiled_code, pat_patctl.jit);+ }+ if ((pat_patctl.control & CTL_MEMORY) != 0) show_memory_info();+ if ((pat_patctl.control & CTL_FRAMESIZE) != 0) show_framesize();+ if ((pat_patctl.control & CTL_ANYINFO) != 0)+ {+ rc = show_pattern_info();+ if (rc != PR_OK) return rc;+ }+ break;++ /* Save the stack of compiled patterns to a file, then empty the stack. */++ case CMD_SAVE:+ if (patstacknext <= 0)+ {+ fprintf(outfile, "** No stacked patterns to save\n");+ return PR_OK;+ }++ rc = open_file(argptr+1, BINARY_OUTPUT_MODE, &f, "#save");+ if (rc != PR_OK) return rc;++ PCRE2_SERIALIZE_ENCODE(rc, patstack, patstacknext, &serial, &serial_size,+ general_context);+ if (rc < 0)+ {+ fclose(f);+ if (!serial_error(rc, "Serialization")) return PR_ABEND;+ break;+ }++ /* Write the length at the start of the file to make it straightforward to+ get the right memory when re-loading. This saves having to read the file size+ in different operating systems. To allow for different endianness (even+ though reloading with the opposite endianness does not work), write the+ length byte-by-byte. */++ for (i = 0; i < 4; i++) fputc((serial_size >> (i*8)) & 255, f);+ if (fwrite(serial, 1, serial_size, f) != serial_size)+ {+ fprintf(outfile, "** Wrong return from fwrite()\n");+ fclose(f);+ return PR_ABEND;+ }++ fclose(f);+ PCRE2_SERIALIZE_FREE(serial);+ while(patstacknext > 0)+ {+ SET(compiled_code, patstack[--patstacknext]);+ SUB1(pcre2_code_free, compiled_code);+ }+ SET(compiled_code, NULL);+ break;++ /* Load a set of compiled patterns from a file onto the stack */++ case CMD_LOAD:+ rc = open_file(argptr+1, BINARY_INPUT_MODE, &f, "#load");+ if (rc != PR_OK) return rc;++ serial_size = 0;+ for (i = 0; i < 4; i++) serial_size |= fgetc(f) << (i*8);++ serial = malloc(serial_size);+ if (serial == NULL)+ {+ fprintf(outfile, "** Failed to get memory (size %" SIZ_FORM ") for #load\n",+ SIZ_CAST serial_size);+ fclose(f);+ return PR_ABEND;+ }++ i = fread(serial, 1, serial_size, f);+ fclose(f);++ if (i != serial_size)+ {+ fprintf(outfile, "** Wrong return from fread()\n");+ yield = PR_ABEND;+ }+ else+ {+ PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(rc, serial);+ if (rc < 0)+ {+ if (!serial_error(rc, "Get number of codes")) yield = PR_ABEND;+ }+ else+ {+ if (rc + patstacknext > PATSTACKSIZE)+ {+ fprintf(outfile, "** Not enough space on pattern stack for %d pattern%s\n",+ rc, (rc == 1)? "" : "s");+ rc = PATSTACKSIZE - patstacknext;+ fprintf(outfile, "** Decoding %d pattern%s\n", rc,+ (rc == 1)? "" : "s");+ }+ PCRE2_SERIALIZE_DECODE(rc, patstack + patstacknext, rc, serial,+ general_context);+ if (rc < 0)+ {+ if (!serial_error(rc, "Deserialization")) yield = PR_ABEND;+ }+ else patstacknext += rc;+ }+ }++ free(serial);+ break;++ /* Load a set of binary tables into tables3. */++ case CMD_LOADTABLES:+ rc = open_file(argptr+1, BINARY_INPUT_MODE, &f, "#loadtables");+ if (rc != PR_OK) return rc;++ if (tables3 == NULL)+ {+ (void)PCRE2_CONFIG(PCRE2_CONFIG_TABLES_LENGTH, &loadtables_length);+ tables3 = malloc(loadtables_length);+ }++ if (tables3 == NULL)+ {+ fprintf(outfile, "** Failed: malloc failed for #loadtables\n");+ yield = PR_ABEND;+ }+ else if (fread(tables3, 1, loadtables_length, f) != loadtables_length)+ {+ fprintf(outfile, "** Wrong return from fread()\n");+ yield = PR_ABEND;+ }++ fclose(f);+ break;+ }++return yield;+}++++/*************************************************+* Process pattern line *+*************************************************/++/* This function is called when the input buffer contains the start of a+pattern. The first character is known to be a valid delimiter. The pattern is+read, modifiers are interpreted, and a suitable local context is set up for+this test. The pattern is then compiled.++Arguments: none++Returns: PR_OK continue processing next line+ PR_SKIP skip to a blank line+ PR_ABEND abort the pcre2test run+*/++static int+process_pattern(void)+{+BOOL utf;+uint32_t k;+uint8_t *p = buffer;+unsigned int delimiter = *p++;+int errorcode;+void *use_pat_context;+uint32_t use_forbid_utf = forbid_utf;+PCRE2_SIZE patlen;+PCRE2_SIZE valgrind_access_length;+PCRE2_SIZE erroroffset;++/* The perltest.sh script supports only / as a delimiter. */++if (restrict_for_perl_test && delimiter != '/')+ {+ fprintf(outfile, "** The only allowed delimiter after #perltest is '/'\n");+ return PR_ABEND; + } ++/* Initialize the context and pattern/data controls for this test from the+defaults. */++PATCTXCPY(pat_context, default_pat_context);+memcpy(&pat_patctl, &def_patctl, sizeof(patctl));++/* Find the end of the pattern, reading more lines if necessary. */++for(;;)+ {+ while (*p != 0)+ {+ if (*p == '\\' && p[1] != 0) p++;+ else if (*p == delimiter) break;+ p++;+ }+ if (*p != 0) break;+ if ((p = extend_inputline(infile, p, " > ")) == NULL)+ {+ fprintf(outfile, "** Unexpected EOF\n");+ return PR_ABEND;+ }+ if (!INTERACTIVE(infile)) fprintf(outfile, "%s", (char *)p);+ }++/* If the first character after the delimiter is backslash, make the pattern+end with backslash. This is purely to provide a way of testing for the error+message when a pattern ends with backslash. */++if (p[1] == '\\') *p++ = '\\';++/* Terminate the pattern at the delimiter, and compute the length. */++*p++ = 0;+patlen = p - buffer - 2;++/* Look for modifiers and options after the final delimiter. */++if (!decode_modifiers(p, CTX_PAT, &pat_patctl, NULL)) return PR_SKIP;++/* Note that the match_invalid_utf option also sets utf when passed to+pcre2_compile(). */++utf = (pat_patctl.options & (PCRE2_UTF|PCRE2_MATCH_INVALID_UTF)) != 0;++/* The utf8_input modifier is not allowed in 8-bit mode, and is mutually+exclusive with the utf modifier. */++if ((pat_patctl.control & CTL_UTF8_INPUT) != 0)+ {+ if (test_mode == PCRE8_MODE)+ {+ fprintf(outfile, "** The utf8_input modifier is not allowed in 8-bit mode\n");+ return PR_SKIP;+ }+ if (utf)+ {+ fprintf(outfile, "** The utf and utf8_input modifiers are mutually exclusive\n");+ return PR_SKIP;+ }+ }++/* The convert and posix modifiers are mutually exclusive. */++if (pat_patctl.convert_type != CONVERT_UNSET &&+ (pat_patctl.control & CTL_POSIX) != 0)+ {+ fprintf(outfile, "** The convert and posix modifiers are mutually exclusive\n");+ return PR_SKIP;+ }++/* Check for mutually exclusive control modifiers. At present, these are all in+the first control word. */++for (k = 0; k < sizeof(exclusive_pat_controls)/sizeof(uint32_t); k++)+ {+ uint32_t c = pat_patctl.control & exclusive_pat_controls[k];+ if (c != 0 && c != (c & (~c+1)))+ {+ show_controls(c, 0, "** Not allowed together:");+ fprintf(outfile, "\n");+ return PR_SKIP;+ }+ }++/* Assume full JIT compile for jitverify and/or jitfast if nothing else was+specified. */++if (pat_patctl.jit == 0 &&+ (pat_patctl.control & (CTL_JITVERIFY|CTL_JITFAST)) != 0)+ pat_patctl.jit = JIT_DEFAULT;++/* Now copy the pattern to pbuffer8 for use in 8-bit testing and for reflecting+in callouts. Convert from hex if requested (literal strings in quotes may be+present within the hexadecimal pairs). The result must necessarily be fewer+characters so will always fit in pbuffer8. */++if ((pat_patctl.control & CTL_HEXPAT) != 0)+ {+ uint8_t *pp, *pt;+ uint32_t c, d;++ pt = pbuffer8;+ for (pp = buffer + 1; *pp != 0; pp++)+ {+ if (isspace(*pp)) continue;+ c = *pp++;++ /* Handle a literal substring */++ if (c == '\'' || c == '"')+ {+ uint8_t *pq = pp;+ for (;; pp++)+ {+ d = *pp;+ if (d == 0)+ {+ fprintf(outfile, "** Missing closing quote in hex pattern: "+ "opening quote is at offset %" PTR_FORM ".\n", pq - buffer - 2);+ return PR_SKIP;+ }+ if (d == c) break;+ *pt++ = d;+ }+ }++ /* Expect a hex pair */++ else+ {+ if (!isxdigit(c))+ {+ fprintf(outfile, "** Unexpected non-hex-digit '%c' at offset %"+ PTR_FORM " in hex pattern: quote missing?\n", c, pp - buffer - 2);+ return PR_SKIP;+ }+ if (*pp == 0)+ {+ fprintf(outfile, "** Odd number of digits in hex pattern\n");+ return PR_SKIP;+ }+ d = *pp;+ if (!isxdigit(d))+ {+ fprintf(outfile, "** Unexpected non-hex-digit '%c' at offset %"+ PTR_FORM " in hex pattern: quote missing?\n", d, pp - buffer - 1);+ return PR_SKIP;+ }+ c = toupper(c);+ d = toupper(d);+ *pt++ = ((isdigit(c)? (c - '0') : (c - 'A' + 10)) << 4) ++ (isdigit(d)? (d - '0') : (d - 'A' + 10));+ }+ }+ *pt = 0;+ patlen = pt - pbuffer8;+ }++/* If not a hex string, process for repetition expansion if requested. */++else if ((pat_patctl.control & CTL_EXPAND) != 0)+ {+ uint8_t *pp, *pt;++ pt = pbuffer8;+ for (pp = buffer + 1; *pp != 0; pp++)+ {+ uint8_t *pc = pp;+ uint32_t count = 1;+ size_t length = 1;++ /* Check for replication syntax; if not found, the defaults just set will+ prevail and one character will be copied. */++ if (pp[0] == '\\' && pp[1] == '[')+ {+ uint8_t *pe;+ for (pe = pp + 2; *pe != 0; pe++)+ {+ if (pe[0] == ']' && pe[1] == '{')+ {+ uint32_t clen = pe - pc - 2;+ uint32_t i = 0;+ unsigned long uli;+ char *endptr;++ pe += 2;+ uli = strtoul((const char *)pe, &endptr, 10);+ if (U32OVERFLOW(uli))+ {+ fprintf(outfile, "** Pattern repeat count too large\n");+ return PR_SKIP;+ }++ i = (uint32_t)uli;+ pe = (uint8_t *)endptr;+ if (*pe == '}')+ {+ if (i == 0)+ {+ fprintf(outfile, "** Zero repeat not allowed\n");+ return PR_SKIP;+ }+ pc += 2;+ count = i;+ length = clen;+ pp = pe;+ break;+ }+ }+ }+ }++ /* Add to output. If the buffer is too small expand it. The function for+ expanding buffers always keeps buffer and pbuffer8 in step as far as their+ size goes. */++ while (pt + count * length > pbuffer8 + pbuffer8_size)+ {+ size_t pc_offset = pc - buffer;+ size_t pp_offset = pp - buffer;+ size_t pt_offset = pt - pbuffer8;+ expand_input_buffers();+ pc = buffer + pc_offset;+ pp = buffer + pp_offset;+ pt = pbuffer8 + pt_offset;+ }++ for (; count > 0; count--)+ {+ memcpy(pt, pc, length);+ pt += length;+ }+ }++ *pt = 0;+ patlen = pt - pbuffer8;++ if ((pat_patctl.control & CTL_INFO) != 0)+ fprintf(outfile, "Expanded: %s\n", pbuffer8);+ }++/* Neither hex nor expanded, just copy the input verbatim. */++else+ {+ strncpy((char *)pbuffer8, (char *)(buffer+1), patlen + 1);+ }++/* Sort out character tables */++if (pat_patctl.locale[0] != 0)+ {+ if (pat_patctl.tables_id != 0)+ {+ fprintf(outfile, "** 'Locale' and 'tables' must not both be set\n");+ return PR_SKIP;+ }+ if (setlocale(LC_CTYPE, (const char *)pat_patctl.locale) == NULL)+ {+ fprintf(outfile, "** Failed to set locale '%s'\n", pat_patctl.locale);+ return PR_SKIP;+ }+ if (strcmp((const char *)pat_patctl.locale, (const char *)locale_name) != 0)+ {+ strcpy((char *)locale_name, (char *)pat_patctl.locale);+ if (locale_tables != NULL) free((void *)locale_tables);+ PCRE2_MAKETABLES(locale_tables);+ }+ use_tables = locale_tables;+ }++else switch (pat_patctl.tables_id)+ {+ case 0: use_tables = NULL; break;+ case 1: use_tables = tables1; break;+ case 2: use_tables = tables2; break;++ case 3:+ if (tables3 == NULL)+ {+ fprintf(outfile, "** 'Tables = 3' is invalid: binary tables have not "+ "been loaded\n");+ return PR_SKIP;+ }+ use_tables = tables3;+ break;++ default:+ fprintf(outfile, "** 'Tables' must specify 0, 1, 2, or 3.\n");+ return PR_SKIP;+ }++PCRE2_SET_CHARACTER_TABLES(pat_context, use_tables);++/* Set up for the stackguard test. */++if (pat_patctl.stackguard_test != 0)+ {+ PCRE2_SET_COMPILE_RECURSION_GUARD(pat_context, stack_guard, NULL);+ }++/* Handle compiling via the POSIX interface, which doesn't support the+timing, showing, or debugging options, nor the ability to pass over+local character tables. Neither does it have 16-bit or 32-bit support. */++if ((pat_patctl.control & CTL_POSIX) != 0)+ {+#ifdef SUPPORT_PCRE2_8+ int rc;+ int cflags = 0;+ const char *msg = "** Ignored with POSIX interface:";+#endif++ if (test_mode != PCRE8_MODE)+ {+ fprintf(outfile, "** The POSIX interface is available only in 8-bit mode\n");+ return PR_SKIP;+ }++#ifdef SUPPORT_PCRE2_8+ /* Check for features that the POSIX interface does not support. */++ if (pat_patctl.locale[0] != 0) prmsg(&msg, "locale");+ if (pat_patctl.replacement[0] != 0) prmsg(&msg, "replace");+ if (pat_patctl.tables_id != 0) prmsg(&msg, "tables");+ if (pat_patctl.stackguard_test != 0) prmsg(&msg, "stackguard");+ if (timeit > 0) prmsg(&msg, "timing");+ if (pat_patctl.jit != 0) prmsg(&msg, "JIT");++ if ((pat_patctl.options & ~POSIX_SUPPORTED_COMPILE_OPTIONS) != 0)+ {+ show_compile_options(+ pat_patctl.options & ~POSIX_SUPPORTED_COMPILE_OPTIONS, msg, "");+ msg = "";+ }++ if ((FLD(pat_context, extra_options) &+ ~POSIX_SUPPORTED_COMPILE_EXTRA_OPTIONS) != 0)+ {+ show_compile_extra_options(+ FLD(pat_context, extra_options) & ~POSIX_SUPPORTED_COMPILE_EXTRA_OPTIONS,+ msg, "");+ msg = "";+ }++ if ((pat_patctl.control & ~POSIX_SUPPORTED_COMPILE_CONTROLS) != 0 ||+ (pat_patctl.control2 & ~POSIX_SUPPORTED_COMPILE_CONTROLS2) != 0)+ {+ show_controls(pat_patctl.control & ~POSIX_SUPPORTED_COMPILE_CONTROLS,+ pat_patctl.control2 & ~POSIX_SUPPORTED_COMPILE_CONTROLS2, msg);+ msg = "";+ }++ if (local_newline_default != 0) prmsg(&msg, "#newline_default");+ if (FLD(pat_context, max_pattern_length) != PCRE2_UNSET)+ prmsg(&msg, "max_pattern_length");+ if (FLD(pat_context, parens_nest_limit) != PARENS_NEST_DEFAULT)+ prmsg(&msg, "parens_nest_limit");++ if (msg[0] == 0) fprintf(outfile, "\n");++ /* Translate PCRE2 options to POSIX options and then compile. */++ if (utf) cflags |= REG_UTF;+ if ((pat_patctl.control & CTL_POSIX_NOSUB) != 0) cflags |= REG_NOSUB;+ if ((pat_patctl.options & PCRE2_UCP) != 0) cflags |= REG_UCP;+ if ((pat_patctl.options & PCRE2_CASELESS) != 0) cflags |= REG_ICASE;+ if ((pat_patctl.options & PCRE2_LITERAL) != 0) cflags |= REG_NOSPEC;+ if ((pat_patctl.options & PCRE2_MULTILINE) != 0) cflags |= REG_NEWLINE;+ if ((pat_patctl.options & PCRE2_DOTALL) != 0) cflags |= REG_DOTALL;+ if ((pat_patctl.options & PCRE2_UNGREEDY) != 0) cflags |= REG_UNGREEDY;++ if ((pat_patctl.control & (CTL_HEXPAT|CTL_USE_LENGTH)) != 0)+ {+ preg.re_endp = (char *)pbuffer8 + patlen;+ cflags |= REG_PEND;+ }++ rc = regcomp(&preg, (char *)pbuffer8, cflags);++ /* Compiling failed */++ if (rc != 0)+ {+ size_t bsize, usize;+ int psize;++ preg.re_pcre2_code = NULL; /* In case something was left in there */+ preg.re_match_data = NULL;++ bsize = (pat_patctl.regerror_buffsize != 0)?+ pat_patctl.regerror_buffsize : pbuffer8_size;+ if (bsize + 8 < pbuffer8_size)+ memcpy(pbuffer8 + bsize, "DEADBEEF", 8);+ usize = regerror(rc, &preg, (char *)pbuffer8, bsize);++ /* Inside regerror(), snprintf() is used. If the buffer is too small, some+ versions of snprintf() put a zero byte at the end, but others do not.+ Therefore, we print a maximum of one less than the size of the buffer. */++ psize = (int)bsize - 1;+ fprintf(outfile, "Failed: POSIX code %d: %.*s\n", rc, psize, pbuffer8);+ if (usize > bsize)+ {+ fprintf(outfile, "** regerror() message truncated\n");+ if (memcmp(pbuffer8 + bsize, "DEADBEEF", 8) != 0)+ fprintf(outfile, "** regerror() buffer overflow\n");+ }+ return PR_SKIP;+ }++ /* Compiling succeeded. Check that the values in the preg block are sensible.+ It can happen that pcre2test is accidentally linked with a different POSIX+ library which succeeds, but of course puts different things into preg. In+ this situation, calling regfree() may cause a segfault (or invalid free() in+ valgrind), so ensure that preg.re_pcre2_code is NULL, which suppresses the+ calling of regfree() on exit. */++ if (preg.re_pcre2_code == NULL ||+ ((pcre2_real_code_8 *)preg.re_pcre2_code)->magic_number != MAGIC_NUMBER ||+ ((pcre2_real_code_8 *)preg.re_pcre2_code)->top_bracket != preg.re_nsub ||+ preg.re_match_data == NULL ||+ preg.re_cflags != cflags)+ {+ fprintf(outfile,+ "** The regcomp() function returned zero (success), but the values set\n"+ "** in the preg block are not valid for PCRE2. Check that pcre2test is\n"+ "** linked with PCRE2's pcre2posix module (-lpcre2-posix) and not with\n"+ "** some other POSIX regex library.\n**\n");+ preg.re_pcre2_code = NULL;+ return PR_ABEND;+ }++ return PR_OK;+#endif /* SUPPORT_PCRE2_8 */+ }++/* Handle compiling via the native interface. Controls that act later are+ignored with "push". Replacements are locked out. */++if ((pat_patctl.control & (CTL_PUSH|CTL_PUSHCOPY|CTL_PUSHTABLESCOPY)) != 0)+ {+ if (pat_patctl.replacement[0] != 0)+ {+ fprintf(outfile, "** Replacement text is not supported with 'push'.\n");+ return PR_OK;+ }+ if ((pat_patctl.control & ~PUSH_SUPPORTED_COMPILE_CONTROLS) != 0 ||+ (pat_patctl.control2 & ~PUSH_SUPPORTED_COMPILE_CONTROLS2) != 0)+ {+ show_controls(pat_patctl.control & ~PUSH_SUPPORTED_COMPILE_CONTROLS,+ pat_patctl.control2 & ~PUSH_SUPPORTED_COMPILE_CONTROLS2,+ "** Ignored when compiled pattern is stacked with 'push':");+ fprintf(outfile, "\n");+ }+ if ((pat_patctl.control & PUSH_COMPILE_ONLY_CONTROLS) != 0 ||+ (pat_patctl.control2 & PUSH_COMPILE_ONLY_CONTROLS2) != 0)+ {+ show_controls(pat_patctl.control & PUSH_COMPILE_ONLY_CONTROLS,+ pat_patctl.control2 & PUSH_COMPILE_ONLY_CONTROLS2,+ "** Applies only to compile when pattern is stacked with 'push':");+ fprintf(outfile, "\n");+ }+ }++/* Convert the input in non-8-bit modes. */++errorcode = 0;++#ifdef SUPPORT_PCRE2_16+if (test_mode == PCRE16_MODE) errorcode = to16(pbuffer8, utf, &patlen);+#endif++#ifdef SUPPORT_PCRE2_32+if (test_mode == PCRE32_MODE) errorcode = to32(pbuffer8, utf, &patlen);+#endif++switch(errorcode)+ {+ case -1:+ fprintf(outfile, "** Failed: invalid UTF-8 string cannot be "+ "converted to %d-bit string\n", (test_mode == PCRE16_MODE)? 16:32);+ return PR_SKIP;++ case -2:+ fprintf(outfile, "** Failed: character value greater than 0x10ffff "+ "cannot be converted to UTF\n");+ return PR_SKIP;++ case -3:+ fprintf(outfile, "** Failed: character value greater than 0xffff "+ "cannot be converted to 16-bit in non-UTF mode\n");+ return PR_SKIP;++ default:+ break;+ }++/* The pattern is now in pbuffer[8|16|32], with the length in code units in+patlen. If it is to be converted, copy the result back afterwards so that it+ends up back in the usual place. */++if (pat_patctl.convert_type != CONVERT_UNSET)+ {+ int rc;+ int convert_return = PR_OK;+ uint32_t convert_options = pat_patctl.convert_type;+ void *converted_pattern;+ PCRE2_SIZE converted_length;++ if (pat_patctl.convert_length != 0)+ {+ converted_length = pat_patctl.convert_length;+ converted_pattern = malloc(converted_length * code_unit_size);+ if (converted_pattern == NULL)+ {+ fprintf(outfile, "** Failed: malloc failed for converted pattern\n");+ return PR_SKIP;+ }+ }+ else converted_pattern = NULL; /* Let the library allocate */++ if (utf) convert_options |= PCRE2_CONVERT_UTF;+ if ((pat_patctl.options & PCRE2_NO_UTF_CHECK) != 0)+ convert_options |= PCRE2_CONVERT_NO_UTF_CHECK;++ CONCTXCPY(con_context, default_con_context);++ if (pat_patctl.convert_glob_escape != 0)+ {+ uint32_t escape = (pat_patctl.convert_glob_escape == '0')? 0 :+ pat_patctl.convert_glob_escape;+ PCRE2_SET_GLOB_ESCAPE(rc, con_context, escape);+ if (rc != 0)+ {+ fprintf(outfile, "** Invalid glob escape '%c'\n",+ pat_patctl.convert_glob_escape);+ convert_return = PR_SKIP;+ goto CONVERT_FINISH;+ }+ }++ if (pat_patctl.convert_glob_separator != 0)+ {+ PCRE2_SET_GLOB_SEPARATOR(rc, con_context, pat_patctl.convert_glob_separator);+ if (rc != 0)+ {+ fprintf(outfile, "** Invalid glob separator '%c'\n",+ pat_patctl.convert_glob_separator);+ convert_return = PR_SKIP;+ goto CONVERT_FINISH;+ }+ }++ PCRE2_PATTERN_CONVERT(rc, pbuffer, patlen, convert_options,+ &converted_pattern, &converted_length, con_context);++ if (rc != 0)+ {+ fprintf(outfile, "** Pattern conversion error at offset %" SIZ_FORM ": ",+ SIZ_CAST converted_length);+ convert_return = print_error_message(rc, "", "\n")? PR_SKIP:PR_ABEND;+ }++ /* Output the converted pattern, then copy it. */++ else+ {+ PCHARSV(converted_pattern, 0, converted_length, utf, outfile);+ fprintf(outfile, "\n");+ patlen = converted_length;+ CONVERT_COPY(pbuffer, converted_pattern, converted_length + 1);+ }++ /* Free the converted pattern. */++ CONVERT_FINISH:+ if (pat_patctl.convert_length != 0)+ free(converted_pattern);+ else+ PCRE2_CONVERTED_PATTERN_FREE(converted_pattern);++ /* Return if conversion was unsuccessful. */++ if (convert_return != PR_OK) return convert_return;+ }++/* By default we pass a zero-terminated pattern, but a length is passed if+"use_length" was specified or this is a hex pattern (which might contain binary+zeros). When valgrind is supported, arrange for the unused part of the buffer+to be marked as no access. */++valgrind_access_length = patlen;+if ((pat_patctl.control & (CTL_HEXPAT|CTL_USE_LENGTH)) == 0)+ {+ patlen = PCRE2_ZERO_TERMINATED;+ valgrind_access_length += 1; /* For the terminating zero */+ }++#ifdef SUPPORT_VALGRIND+#ifdef SUPPORT_PCRE2_8+if (test_mode == PCRE8_MODE && pbuffer8 != NULL)+ {+ VALGRIND_MAKE_MEM_NOACCESS(pbuffer8 + valgrind_access_length,+ pbuffer8_size - valgrind_access_length);+ }+#endif+#ifdef SUPPORT_PCRE2_16+if (test_mode == PCRE16_MODE && pbuffer16 != NULL)+ {+ VALGRIND_MAKE_MEM_NOACCESS(pbuffer16 + valgrind_access_length,+ pbuffer16_size - valgrind_access_length*sizeof(uint16_t));+ }+#endif+#ifdef SUPPORT_PCRE2_32+if (test_mode == PCRE32_MODE && pbuffer32 != NULL)+ {+ VALGRIND_MAKE_MEM_NOACCESS(pbuffer32 + valgrind_access_length,+ pbuffer32_size - valgrind_access_length*sizeof(uint32_t));+ }+#endif+#else /* Valgrind not supported */+(void)valgrind_access_length; /* Avoid compiler warning */+#endif++/* If #newline_default has been used and the library was not compiled with an+appropriate default newline setting, local_newline_default will be non-zero. We+use this if there is no explicit newline modifier. */++if ((pat_patctl.control2 & CTL2_NL_SET) == 0 && local_newline_default != 0)+ {+ SETFLD(pat_context, newline_convention, local_newline_default);+ }++/* The null_context modifier is used to test calling pcre2_compile() with a+NULL context. */++use_pat_context = ((pat_patctl.control & CTL_NULLCONTEXT) != 0)?+ NULL : PTR(pat_context);++/* If PCRE2_LITERAL is set, set use_forbid_utf zero because PCRE2_NEVER_UTF+and PCRE2_NEVER_UCP are invalid with it. */++if ((pat_patctl.options & PCRE2_LITERAL) != 0) use_forbid_utf = 0;++/* Compile many times when timing. */++if (timeit > 0)+ {+ int i;+ clock_t time_taken = 0;+ for (i = 0; i < timeit; i++)+ {+ clock_t start_time = clock();+ PCRE2_COMPILE(compiled_code, pbuffer, patlen,+ pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset,+ use_pat_context);+ time_taken += clock() - start_time;+ if (TEST(compiled_code, !=, NULL))+ { SUB1(pcre2_code_free, compiled_code); }+ }+ total_compile_time += time_taken;+ fprintf(outfile, "Compile time %.4f milliseconds\n",+ (((double)time_taken * 1000.0) / (double)timeit) /+ (double)CLOCKS_PER_SEC);+ }++/* A final compile that is used "for real". */++PCRE2_COMPILE(compiled_code, pbuffer, patlen, pat_patctl.options|use_forbid_utf,+ &errorcode, &erroroffset, use_pat_context);++/* Call the JIT compiler if requested. When timing, we must free and recompile+the pattern each time because that is the only way to free the JIT compiled+code. We know that compilation will always succeed. */++if (TEST(compiled_code, !=, NULL) && pat_patctl.jit != 0)+ {+ if (timeit > 0)+ {+ int i;+ clock_t time_taken = 0;++ for (i = 0; i < timeit; i++)+ {+ clock_t start_time;+ SUB1(pcre2_code_free, compiled_code);+ PCRE2_COMPILE(compiled_code, pbuffer, patlen,+ pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset,+ use_pat_context);+ start_time = clock();+ PCRE2_JIT_COMPILE(jitrc, compiled_code, pat_patctl.jit);+ time_taken += clock() - start_time;+ }+ total_jit_compile_time += time_taken;+ fprintf(outfile, "JIT compile %.4f milliseconds\n",+ (((double)time_taken * 1000.0) / (double)timeit) /+ (double)CLOCKS_PER_SEC);+ }+ else+ {+ PCRE2_JIT_COMPILE(jitrc, compiled_code, pat_patctl.jit);+ }+ }++/* If valgrind is supported, mark the pbuffer as accessible again. The 16-bit+and 32-bit buffers can be marked completely undefined, but we must leave the+pattern in the 8-bit buffer defined because it may be read from a callout+during matching. */++#ifdef SUPPORT_VALGRIND+#ifdef SUPPORT_PCRE2_8+if (test_mode == PCRE8_MODE)+ {+ VALGRIND_MAKE_MEM_UNDEFINED(pbuffer8 + valgrind_access_length,+ pbuffer8_size - valgrind_access_length);+ }+#endif+#ifdef SUPPORT_PCRE2_16+if (test_mode == PCRE16_MODE)+ {+ VALGRIND_MAKE_MEM_UNDEFINED(pbuffer16, pbuffer16_size);+ }+#endif+#ifdef SUPPORT_PCRE2_32+if (test_mode == PCRE32_MODE)+ {+ VALGRIND_MAKE_MEM_UNDEFINED(pbuffer32, pbuffer32_size);+ }+#endif+#endif++/* Compilation failed; go back for another re, skipping to blank line+if non-interactive. */++if (TEST(compiled_code, ==, NULL))+ {+ fprintf(outfile, "Failed: error %d at offset %d: ", errorcode,+ (int)erroroffset);+ if (!print_error_message(errorcode, "", "\n")) return PR_ABEND;+ return PR_SKIP;+ }++/* If forbid_utf is non-zero, we are running a non-UTF test. UTF and UCP are+locked out at compile time, but we must also check for occurrences of \P, \p,+and \X, which are only supported when Unicode is supported. */++if (forbid_utf != 0)+ {+ if ((FLD(compiled_code, flags) & PCRE2_HASBKPORX) != 0)+ {+ fprintf(outfile, "** \\P, \\p, and \\X are not allowed after the "+ "#forbid_utf command\n");+ return PR_SKIP;+ }+ }++/* Remember the maximum lookbehind, for partial matching. */++if (pattern_info(PCRE2_INFO_MAXLOOKBEHIND, &maxlookbehind, FALSE) != 0)+ return PR_ABEND;++/* Remember the number of captures. */++if (pattern_info(PCRE2_INFO_CAPTURECOUNT, &maxcapcount, FALSE) < 0)+ return PR_ABEND;++/* If an explicit newline modifier was given, set the information flag in the+pattern so that it is preserved over push/pop. */++if ((pat_patctl.control2 & CTL2_NL_SET) != 0)+ {+ SETFLD(compiled_code, flags, FLD(compiled_code, flags) | PCRE2_NL_SET);+ }++/* Output code size and other information if requested. */++if ((pat_patctl.control & CTL_MEMORY) != 0) show_memory_info();+if ((pat_patctl.control & CTL_FRAMESIZE) != 0) show_framesize();+if ((pat_patctl.control & CTL_ANYINFO) != 0)+ {+ int rc = show_pattern_info();+ if (rc != PR_OK) return rc;+ }++/* The "push" control requests that the compiled pattern be remembered on a+stack. This is mainly for testing the serialization functionality. */++if ((pat_patctl.control & CTL_PUSH) != 0)+ {+ if (patstacknext >= PATSTACKSIZE)+ {+ fprintf(outfile, "** Too many pushed patterns (max %d)\n", PATSTACKSIZE);+ return PR_ABEND;+ }+ patstack[patstacknext++] = PTR(compiled_code);+ SET(compiled_code, NULL);+ }++/* The "pushcopy" and "pushtablescopy" controls are similar, but push a+copy of the pattern, the latter with a copy of its character tables. This tests+the pcre2_code_copy() and pcre2_code_copy_with_tables() functions. */++if ((pat_patctl.control & (CTL_PUSHCOPY|CTL_PUSHTABLESCOPY)) != 0)+ {+ if (patstacknext >= PATSTACKSIZE)+ {+ fprintf(outfile, "** Too many pushed patterns (max %d)\n", PATSTACKSIZE);+ return PR_ABEND;+ }+ if ((pat_patctl.control & CTL_PUSHCOPY) != 0)+ {+ PCRE2_CODE_COPY_TO_VOID(patstack[patstacknext++], compiled_code);+ }+ else+ {+ PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(patstack[patstacknext++],+ compiled_code); }+ }++return PR_OK;+}++++/*************************************************+* Check heap, match or depth limit *+*************************************************/++/* This is used for DFA, normal, and JIT fast matching. For DFA matching it+should only be called with the third argument set to PCRE2_ERROR_DEPTHLIMIT.++Arguments:+ pp the subject string+ ulen length of subject or PCRE2_ZERO_TERMINATED+ errnumber defines which limit to test+ msg string to include in final message++Returns: the return from the final match function call+*/++static int+check_match_limit(uint8_t *pp, PCRE2_SIZE ulen, int errnumber, const char *msg)+{+int capcount;+uint32_t min = 0;+uint32_t mid = 64;+uint32_t max = UINT32_MAX;++PCRE2_SET_MATCH_LIMIT(dat_context, max);+PCRE2_SET_DEPTH_LIMIT(dat_context, max);+PCRE2_SET_HEAP_LIMIT(dat_context, max);++for (;;)+ {+ uint32_t stack_start = 0;++ if (errnumber == PCRE2_ERROR_HEAPLIMIT)+ {+ PCRE2_SET_HEAP_LIMIT(dat_context, mid);+ }+ else if (errnumber == PCRE2_ERROR_MATCHLIMIT)+ {+ PCRE2_SET_MATCH_LIMIT(dat_context, mid);+ }+ else+ {+ PCRE2_SET_DEPTH_LIMIT(dat_context, mid);+ }++ if ((dat_datctl.control & CTL_DFA) != 0)+ {+ stack_start = DFA_START_RWS_SIZE/1024;+ if (dfa_workspace == NULL)+ dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));+ if (dfa_matched++ == 0)+ dfa_workspace[0] = -1; /* To catch bad restart */+ PCRE2_DFA_MATCH(capcount, compiled_code, pp, ulen, dat_datctl.offset,+ dat_datctl.options, match_data,+ PTR(dat_context), dfa_workspace, DFA_WS_DIMENSION);+ }++ else if ((pat_patctl.control & CTL_JITFAST) != 0)+ PCRE2_JIT_MATCH(capcount, compiled_code, pp, ulen, dat_datctl.offset,+ dat_datctl.options, match_data, PTR(dat_context));++ else+ {+ stack_start = START_FRAMES_SIZE/1024;+ PCRE2_MATCH(capcount, compiled_code, pp, ulen, dat_datctl.offset,+ dat_datctl.options, match_data, PTR(dat_context));+ }++ if (capcount == errnumber)+ {+ if ((mid & 0x80000000u) != 0)+ {+ fprintf(outfile, "Can't find minimum %s limit: check pattern for "+ "restriction\n", msg);+ break;+ }++ min = mid;+ mid = (mid == max - 1)? max : (max != UINT32_MAX)? (min + max)/2 : mid*2;+ }+ else if (capcount >= 0 ||+ capcount == PCRE2_ERROR_NOMATCH ||+ capcount == PCRE2_ERROR_PARTIAL)+ {+ /* If we've not hit the error with a heap limit less than the size of the+ initial stack frame vector (for pcre2_match()) or the initial stack+ workspace vector (for pcre2_dfa_match()), the heap is not being used, so+ the minimum limit is zero; there's no need to go on. The other limits are+ always greater than zero. */++ if (errnumber == PCRE2_ERROR_HEAPLIMIT && mid < stack_start)+ {+ fprintf(outfile, "Minimum %s limit = 0\n", msg);+ break;+ }+ if (mid == min + 1)+ {+ fprintf(outfile, "Minimum %s limit = %d\n", msg, mid);+ break;+ }+ max = mid;+ mid = (min + max)/2;+ }+ else break; /* Some other error */+ }++return capcount;+}++++/*************************************************+* Substitute callout function *+*************************************************/++/* Called from pcre2_substitute() when the substitute_callout modifier is set.+Print out the data that is passed back. The substitute callout block is+identical for all code unit widths, so we just pick one.++Arguments:+ scb pointer to substitute callout block+ data_ptr callout data++Returns: nothing+*/++static int+substitute_callout_function(pcre2_substitute_callout_block_8 *scb,+ void *data_ptr)+{+int yield = 0;+BOOL utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;+(void)data_ptr; /* Not used */++fprintf(outfile, "%2d(%d) Old %" SIZ_FORM " %" SIZ_FORM " \"",+ scb->subscount, scb->oveccount,+ SIZ_CAST scb->ovector[0], SIZ_CAST scb->ovector[1]);++PCHARSV(scb->input, scb->ovector[0], scb->ovector[1] - scb->ovector[0],+ utf, outfile);++fprintf(outfile, "\" New %" SIZ_FORM " %" SIZ_FORM " \"",+ SIZ_CAST scb->output_offsets[0], SIZ_CAST scb->output_offsets[1]);++PCHARSV(scb->output, scb->output_offsets[0],+ scb->output_offsets[1] - scb->output_offsets[0], utf, outfile);++if (scb->subscount == dat_datctl.substitute_stop)+ {+ yield = -1;+ fprintf(outfile, " STOPPED");+ }+else if (scb->subscount == dat_datctl.substitute_skip)+ {+ yield = +1;+ fprintf(outfile, " SKIPPED");+ }++fprintf(outfile, "\"\n");+return yield;+}+++/*************************************************+* Callout function *+*************************************************/++/* Called from a PCRE2 library as a result of the (?C) item. We print out where+we are in the match (unless suppressed). Yield zero unless more callouts than+the fail count, or the callout data is not zero. The only differences in the+callout block for different code unit widths are that the pointers to the+subject, the most recent MARK, and a callout argument string point to strings+of the appropriate width. Casts can be used to deal with this.++Arguments:+ cb a pointer to a callout block+ callout_data_ptr the provided callout data++Returns: 0 or 1 or an error, as determined by settings+*/++static int+callout_function(pcre2_callout_block_8 *cb, void *callout_data_ptr)+{+FILE *f, *fdefault;+uint32_t i, pre_start, post_start, subject_length;+PCRE2_SIZE current_position;+BOOL utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;+BOOL callout_capture = (dat_datctl.control & CTL_CALLOUT_CAPTURE) != 0;+BOOL callout_where = (dat_datctl.control2 & CTL2_CALLOUT_NO_WHERE) == 0;++/* The FILE f is used for echoing the subject string if it is non-NULL. This+happens only once in simple cases, but we want to repeat after any additional+output caused by CALLOUT_EXTRA. */++fdefault = (!first_callout && !callout_capture && cb->callout_string == NULL)?+ NULL : outfile;++if ((dat_datctl.control2 & CTL2_CALLOUT_EXTRA) != 0)+ {+ f = outfile;+ switch (cb->callout_flags)+ {+ case PCRE2_CALLOUT_BACKTRACK:+ fprintf(f, "Backtrack\n");+ break;++ case PCRE2_CALLOUT_STARTMATCH|PCRE2_CALLOUT_BACKTRACK:+ fprintf(f, "Backtrack\nNo other matching paths\n");+ /* Fall through */++ case PCRE2_CALLOUT_STARTMATCH:+ fprintf(f, "New match attempt\n");+ break;++ default:+ f = fdefault;+ break;+ }+ }+else f = fdefault;++/* For a callout with a string argument, show the string first because there+isn't a tidy way to fit it in the rest of the data. */++if (cb->callout_string != NULL)+ {+ uint32_t delimiter = CODE_UNIT(cb->callout_string, -1);+ fprintf(outfile, "Callout (%" SIZ_FORM "): %c",+ SIZ_CAST cb->callout_string_offset, delimiter);+ PCHARSV(cb->callout_string, 0,+ cb->callout_string_length, utf, outfile);+ for (i = 0; callout_start_delims[i] != 0; i++)+ if (delimiter == callout_start_delims[i])+ {+ delimiter = callout_end_delims[i];+ break;+ }+ fprintf(outfile, "%c", delimiter);+ if (!callout_capture) fprintf(outfile, "\n");+ }++/* Show captured strings if required */++if (callout_capture)+ {+ if (cb->callout_string == NULL)+ fprintf(outfile, "Callout %d:", cb->callout_number);+ fprintf(outfile, " last capture = %d\n", cb->capture_last);+ for (i = 2; i < cb->capture_top * 2; i += 2)+ {+ fprintf(outfile, "%2d: ", i/2);+ if (cb->offset_vector[i] == PCRE2_UNSET)+ fprintf(outfile, "<unset>");+ else+ {+ PCHARSV(cb->subject, cb->offset_vector[i],+ cb->offset_vector[i+1] - cb->offset_vector[i], utf, f);+ }+ fprintf(outfile, "\n");+ }+ }++/* Unless suppressed, re-print the subject in canonical form (with escapes for+non-printing characters), the first time, or if giving full details. On+subsequent calls in the same match, we use PCHARS() just to find the printed+lengths of the substrings. */++if (callout_where)+ {+ if (f != NULL) fprintf(f, "--->");++ /* The subject before the match start. */++ PCHARS(pre_start, cb->subject, 0, cb->start_match, utf, f);++ /* If a lookbehind is involved, the current position may be earlier than the+ match start. If so, use the match start instead. */++ current_position = (cb->current_position >= cb->start_match)?+ cb->current_position : cb->start_match;++ /* The subject between the match start and the current position. */++ PCHARS(post_start, cb->subject, cb->start_match,+ current_position - cb->start_match, utf, f);++ /* Print from the current position to the end. */++ PCHARSV(cb->subject, current_position, cb->subject_length - current_position,+ utf, f);++ /* Calculate the total subject printed length (no print). */++ PCHARS(subject_length, cb->subject, 0, cb->subject_length, utf, NULL);++ if (f != NULL) fprintf(f, "\n");++ /* For automatic callouts, show the pattern offset. Otherwise, for a+ numerical callout whose number has not already been shown with captured+ strings, show the number here. A callout with a string argument has been+ displayed above. */++ if (cb->callout_number == 255)+ {+ fprintf(outfile, "%+3d ", (int)cb->pattern_position);+ if (cb->pattern_position > 99) fprintf(outfile, "\n ");+ }+ else+ {+ if (callout_capture || cb->callout_string != NULL) fprintf(outfile, " ");+ else fprintf(outfile, "%3d ", cb->callout_number);+ }++ /* Now show position indicators */++ for (i = 0; i < pre_start; i++) fprintf(outfile, " ");+ fprintf(outfile, "^");++ if (post_start > 0)+ {+ for (i = 0; i < post_start - 1; i++) fprintf(outfile, " ");+ fprintf(outfile, "^");+ }++ for (i = 0; i < subject_length - pre_start - post_start + 4; i++)+ fprintf(outfile, " ");++ if (cb->next_item_length != 0)+ fprintf(outfile, "%.*s", (int)(cb->next_item_length),+ pbuffer8 + cb->pattern_position);+ else+ fprintf(outfile, "End of pattern");++ fprintf(outfile, "\n");+ }++first_callout = FALSE;++/* Show any mark info */++if (cb->mark != last_callout_mark)+ {+ if (cb->mark == NULL)+ fprintf(outfile, "Latest Mark: <unset>\n");+ else+ {+ fprintf(outfile, "Latest Mark: ");+ PCHARSV(cb->mark, -1, -1, utf, outfile);+ putc('\n', outfile);+ }+ last_callout_mark = cb->mark;+ }++/* Show callout data */++if (callout_data_ptr != NULL)+ {+ int callout_data = *((int32_t *)callout_data_ptr);+ if (callout_data != 0)+ {+ fprintf(outfile, "Callout data = %d\n", callout_data);+ return callout_data;+ }+ }++/* Keep count and give the appropriate return code */++callout_count++;++if (cb->callout_number == dat_datctl.cerror[0] &&+ callout_count >= dat_datctl.cerror[1])+ return PCRE2_ERROR_CALLOUT;++if (cb->callout_number == dat_datctl.cfail[0] &&+ callout_count >= dat_datctl.cfail[1])+ return 1;++return 0;+}++++/*************************************************+* Handle *MARK and copy/get tests *+*************************************************/++/* This function is called after complete and partial matches. It runs the+tests for substring extraction.++Arguments:+ utf TRUE for utf+ capcount return from pcre2_match()++Returns: FALSE if print_error_message() fails+*/++static BOOL+copy_and_get(BOOL utf, int capcount)+{+int i;+uint8_t *nptr;++/* Test copy strings by number */++for (i = 0; i < MAXCPYGET && dat_datctl.copy_numbers[i] >= 0; i++)+ {+ int rc;+ PCRE2_SIZE length, length2;+ uint32_t copybuffer[256];+ uint32_t n = (uint32_t)(dat_datctl.copy_numbers[i]);+ length = sizeof(copybuffer)/code_unit_size;+ PCRE2_SUBSTRING_COPY_BYNUMBER(rc, match_data, n, copybuffer, &length);+ if (rc < 0)+ {+ fprintf(outfile, "Copy substring %d failed (%d): ", n, rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else+ {+ PCRE2_SUBSTRING_LENGTH_BYNUMBER(rc, match_data, n, &length2);+ if (rc < 0)+ {+ fprintf(outfile, "Get substring %d length failed (%d): ", n, rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else if (length2 != length)+ {+ fprintf(outfile, "Mismatched substring lengths: %"+ SIZ_FORM " %" SIZ_FORM "\n", SIZ_CAST length, SIZ_CAST length2);+ }+ fprintf(outfile, "%2dC ", n);+ PCHARSV(copybuffer, 0, length, utf, outfile);+ fprintf(outfile, " (%" SIZ_FORM ")\n", SIZ_CAST length);+ }+ }++/* Test copy strings by name */++nptr = dat_datctl.copy_names;+for (;;)+ {+ int rc;+ int groupnumber;+ PCRE2_SIZE length, length2;+ uint32_t copybuffer[256];+ int namelen = strlen((const char *)nptr);+#if defined SUPPORT_PCRE2_16 || defined SUPPORT_PCRE2_32+ PCRE2_SIZE cnl = namelen;+#endif+ if (namelen == 0) break;++#ifdef SUPPORT_PCRE2_8+ if (test_mode == PCRE8_MODE) strcpy((char *)pbuffer8, (char *)nptr);+#endif+#ifdef SUPPORT_PCRE2_16+ if (test_mode == PCRE16_MODE)(void)to16(nptr, utf, &cnl);+#endif+#ifdef SUPPORT_PCRE2_32+ if (test_mode == PCRE32_MODE)(void)to32(nptr, utf, &cnl);+#endif++ PCRE2_SUBSTRING_NUMBER_FROM_NAME(groupnumber, compiled_code, pbuffer);+ if (groupnumber < 0 && groupnumber != PCRE2_ERROR_NOUNIQUESUBSTRING)+ fprintf(outfile, "Number not found for group '%s'\n", nptr);++ length = sizeof(copybuffer)/code_unit_size;+ PCRE2_SUBSTRING_COPY_BYNAME(rc, match_data, pbuffer, copybuffer, &length);+ if (rc < 0)+ {+ fprintf(outfile, "Copy substring '%s' failed (%d): ", nptr, rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else+ {+ PCRE2_SUBSTRING_LENGTH_BYNAME(rc, match_data, pbuffer, &length2);+ if (rc < 0)+ {+ fprintf(outfile, "Get substring '%s' length failed (%d): ", nptr, rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else if (length2 != length)+ {+ fprintf(outfile, "Mismatched substring lengths: %"+ SIZ_FORM " %" SIZ_FORM "\n", SIZ_CAST length, SIZ_CAST length2);+ }+ fprintf(outfile, " C ");+ PCHARSV(copybuffer, 0, length, utf, outfile);+ fprintf(outfile, " (%" SIZ_FORM ") %s", SIZ_CAST length, nptr);+ if (groupnumber >= 0) fprintf(outfile, " (group %d)\n", groupnumber);+ else fprintf(outfile, " (non-unique)\n");+ }+ nptr += namelen + 1;+ }++/* Test get strings by number */++for (i = 0; i < MAXCPYGET && dat_datctl.get_numbers[i] >= 0; i++)+ {+ int rc;+ PCRE2_SIZE length;+ void *gotbuffer;+ uint32_t n = (uint32_t)(dat_datctl.get_numbers[i]);+ PCRE2_SUBSTRING_GET_BYNUMBER(rc, match_data, n, &gotbuffer, &length);+ if (rc < 0)+ {+ fprintf(outfile, "Get substring %d failed (%d): ", n, rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else+ {+ fprintf(outfile, "%2dG ", n);+ PCHARSV(gotbuffer, 0, length, utf, outfile);+ fprintf(outfile, " (%" SIZ_FORM ")\n", SIZ_CAST length);+ PCRE2_SUBSTRING_FREE(gotbuffer);+ }+ }++/* Test get strings by name */++nptr = dat_datctl.get_names;+for (;;)+ {+ PCRE2_SIZE length;+ void *gotbuffer;+ int rc;+ int groupnumber;+ int namelen = strlen((const char *)nptr);+#if defined SUPPORT_PCRE2_16 || defined SUPPORT_PCRE2_32+ PCRE2_SIZE cnl = namelen;+#endif+ if (namelen == 0) break;++#ifdef SUPPORT_PCRE2_8+ if (test_mode == PCRE8_MODE) strcpy((char *)pbuffer8, (char *)nptr);+#endif+#ifdef SUPPORT_PCRE2_16+ if (test_mode == PCRE16_MODE)(void)to16(nptr, utf, &cnl);+#endif+#ifdef SUPPORT_PCRE2_32+ if (test_mode == PCRE32_MODE)(void)to32(nptr, utf, &cnl);+#endif++ PCRE2_SUBSTRING_NUMBER_FROM_NAME(groupnumber, compiled_code, pbuffer);+ if (groupnumber < 0 && groupnumber != PCRE2_ERROR_NOUNIQUESUBSTRING)+ fprintf(outfile, "Number not found for group '%s'\n", nptr);++ PCRE2_SUBSTRING_GET_BYNAME(rc, match_data, pbuffer, &gotbuffer, &length);+ if (rc < 0)+ {+ fprintf(outfile, "Get substring '%s' failed (%d): ", nptr, rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else+ {+ fprintf(outfile, " G ");+ PCHARSV(gotbuffer, 0, length, utf, outfile);+ fprintf(outfile, " (%" SIZ_FORM ") %s", SIZ_CAST length, nptr);+ if (groupnumber >= 0) fprintf(outfile, " (group %d)\n", groupnumber);+ else fprintf(outfile, " (non-unique)\n");+ PCRE2_SUBSTRING_FREE(gotbuffer);+ }+ nptr += namelen + 1;+ }++/* Test getting the complete list of captured strings. */++if ((dat_datctl.control & CTL_GETALL) != 0)+ {+ int rc;+ void **stringlist;+ PCRE2_SIZE *lengths;+ PCRE2_SUBSTRING_LIST_GET(rc, match_data, &stringlist, &lengths);+ if (rc < 0)+ {+ fprintf(outfile, "get substring list failed (%d): ", rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else+ {+ for (i = 0; i < capcount; i++)+ {+ fprintf(outfile, "%2dL ", i);+ PCHARSV(stringlist[i], 0, lengths[i], utf, outfile);+ putc('\n', outfile);+ }+ if (stringlist[i] != NULL)+ fprintf(outfile, "string list not terminated by NULL\n");+ PCRE2_SUBSTRING_LIST_FREE(stringlist);+ }+ }++return TRUE;+}++++/*************************************************+* Show an entire ovector *+*************************************************/++/* This function is called after partial matching or match failure, when the+"allvector" modifier is set. It is a means of checking the contents of the+entire ovector, to ensure no modification of fields that should be unchanged.++Arguments:+ ovector points to the ovector+ oveccount number of pairs++Returns: nothing+*/++static void+show_ovector(PCRE2_SIZE *ovector, uint32_t oveccount)+{+uint32_t i;+for (i = 0; i < 2*oveccount; i += 2)+ {+ PCRE2_SIZE start = ovector[i];+ PCRE2_SIZE end = ovector[i+1];++ fprintf(outfile, "%2d: ", i/2);+ if (start == PCRE2_UNSET && end == PCRE2_UNSET)+ fprintf(outfile, "<unset>\n");+ else if (start == JUNK_OFFSET && end == JUNK_OFFSET)+ fprintf(outfile, "<unchanged>\n");+ else+ fprintf(outfile, "%ld %ld\n", (unsigned long int)start,+ (unsigned long int)end);+ }+}+++/*************************************************+* Process a data line *+*************************************************/++/* The line is in buffer; it will not be empty.++Arguments: none++Returns: PR_OK continue processing next line+ PR_SKIP skip to a blank line+ PR_ABEND abort the pcre2test run+*/++static int+process_data(void)+{+PCRE2_SIZE len, ulen, arg_ulen;+uint32_t gmatched;+uint32_t c, k;+uint32_t g_notempty = 0;+uint8_t *p, *pp, *start_rep;+size_t needlen;+void *use_dat_context;+BOOL utf;+BOOL subject_literal;++PCRE2_SIZE *ovector;+PCRE2_SIZE ovecsave[3];+uint32_t oveccount;++#ifdef SUPPORT_PCRE2_8+uint8_t *q8 = NULL;+#endif+#ifdef SUPPORT_PCRE2_16+uint16_t *q16 = NULL;+#endif+#ifdef SUPPORT_PCRE2_32+uint32_t *q32 = NULL;+#endif++subject_literal = (pat_patctl.control2 & CTL2_SUBJECT_LITERAL) != 0;++/* Copy the default context and data control blocks to the active ones. Then+copy from the pattern the controls that can be set in either the pattern or the+data. This allows them to be overridden in the data line. We do not do this for+options because those that are common apply separately to compiling and+matching. */++DATCTXCPY(dat_context, default_dat_context);+memcpy(&dat_datctl, &def_datctl, sizeof(datctl));+dat_datctl.control |= (pat_patctl.control & CTL_ALLPD);+dat_datctl.control2 |= (pat_patctl.control2 & CTL2_ALLPD);+strcpy((char *)dat_datctl.replacement, (char *)pat_patctl.replacement);+if (dat_datctl.jitstack == 0) dat_datctl.jitstack = pat_patctl.jitstack;++if (dat_datctl.substitute_skip == 0)+ dat_datctl.substitute_skip = pat_patctl.substitute_skip;+if (dat_datctl.substitute_stop == 0)+ dat_datctl.substitute_stop = pat_patctl.substitute_stop;++/* Initialize for scanning the data line. */++#ifdef SUPPORT_PCRE2_8+utf = ((((pat_patctl.control & CTL_POSIX) != 0)?+ ((pcre2_real_code_8 *)preg.re_pcre2_code)->overall_options :+ FLD(compiled_code, overall_options)) & PCRE2_UTF) != 0;+#else+utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;+#endif++start_rep = NULL;+len = strlen((const char *)buffer);+while (len > 0 && isspace(buffer[len-1])) len--;+buffer[len] = 0;+p = buffer;+while (isspace(*p)) p++;++/* Check that the data is well-formed UTF-8 if we're in UTF mode. To create+invalid input to pcre2_match(), you must use \x?? or \x{} sequences. */++if (utf)+ {+ uint8_t *q;+ uint32_t cc;+ int n = 1;+ for (q = p; n > 0 && *q; q += n) n = utf82ord(q, &cc);+ if (n <= 0)+ {+ fprintf(outfile, "** Failed: invalid UTF-8 string cannot be used as input "+ "in UTF mode\n");+ return PR_OK;+ }+ }++#ifdef SUPPORT_VALGRIND+/* Mark the dbuffer as addressable but undefined again. */+if (dbuffer != NULL)+ {+ VALGRIND_MAKE_MEM_UNDEFINED(dbuffer, dbuffer_size);+ }+#endif++/* Allocate a buffer to hold the data line; len+1 is an upper bound on+the number of code units that will be needed (though the buffer may have to be+extended if replication is involved). */++needlen = (size_t)((len+1) * code_unit_size);+if (dbuffer == NULL || needlen >= dbuffer_size)+ {+ while (needlen >= dbuffer_size) dbuffer_size *= 2;+ dbuffer = (uint8_t *)realloc(dbuffer, dbuffer_size);+ if (dbuffer == NULL)+ {+ fprintf(stderr, "pcre2test: realloc(%d) failed\n", (int)dbuffer_size);+ exit(1);+ }+ }+SETCASTPTR(q, dbuffer); /* Sets q8, q16, or q32, as appropriate. */++/* Scan the data line, interpreting data escapes, and put the result into a+buffer of the appropriate width. In UTF mode, input is always UTF-8; otherwise,+in 16- and 32-bit modes, it can be forced to UTF-8 by the utf8_input modifier.+*/++while ((c = *p++) != 0)+ {+ int32_t i = 0;+ size_t replen;++ /* ] may mark the end of a replicated sequence */++ if (c == ']' && start_rep != NULL)+ {+ long li;+ char *endptr;+ size_t qoffset = CAST8VAR(q) - dbuffer;+ size_t rep_offset = start_rep - dbuffer;++ if (*p++ != '{')+ {+ fprintf(outfile, "** Expected '{' after \\[....]\n");+ return PR_OK;+ }++ li = strtol((const char *)p, &endptr, 10);+ if (S32OVERFLOW(li))+ {+ fprintf(outfile, "** Repeat count too large\n");+ return PR_OK;+ }++ p = (uint8_t *)endptr;+ if (*p++ != '}')+ {+ fprintf(outfile, "** Expected '}' after \\[...]{...\n");+ return PR_OK;+ }++ i = (int32_t)li;+ if (i-- == 0)+ {+ fprintf(outfile, "** Zero repeat not allowed\n");+ return PR_OK;+ }++ replen = CAST8VAR(q) - start_rep;+ needlen += replen * i;++ if (needlen >= dbuffer_size)+ {+ while (needlen >= dbuffer_size) dbuffer_size *= 2;+ dbuffer = (uint8_t *)realloc(dbuffer, dbuffer_size);+ if (dbuffer == NULL)+ {+ fprintf(stderr, "pcre2test: realloc(%d) failed\n", (int)dbuffer_size);+ exit(1);+ }+ SETCASTPTR(q, dbuffer + qoffset);+ start_rep = dbuffer + rep_offset;+ }++ while (i-- > 0)+ {+ memcpy(CAST8VAR(q), start_rep, replen);+ SETPLUS(q, replen/code_unit_size);+ }++ start_rep = NULL;+ continue;+ }++ /* Handle a non-escaped character. In non-UTF 32-bit mode with utf8_input+ set, do the fudge for setting the top bit. */++ if (c != '\\' || subject_literal)+ {+ uint32_t topbit = 0;+ if (test_mode == PCRE32_MODE && c == 0xff && *p != 0)+ {+ topbit = 0x80000000;+ c = *p++;+ }+ if ((utf || (pat_patctl.control & CTL_UTF8_INPUT) != 0) &&+ HASUTF8EXTRALEN(c)) { GETUTF8INC(c, p); }+ c |= topbit;+ }++ /* Handle backslash escapes */++ else switch ((c = *p++))+ {+ case '\\': break;+ case 'a': c = CHAR_BEL; break;+ case 'b': c = '\b'; break;+ case 'e': c = CHAR_ESC; break;+ case 'f': c = '\f'; break;+ case 'n': c = '\n'; break;+ case 'r': c = '\r'; break;+ case 't': c = '\t'; break;+ case 'v': c = '\v'; break;++ case '0': case '1': case '2': case '3':+ case '4': case '5': case '6': case '7':+ c -= '0';+ while (i++ < 2 && isdigit(*p) && *p != '8' && *p != '9')+ c = c * 8 + *p++ - '0';+ break;++ case 'o':+ if (*p == '{')+ {+ uint8_t *pt = p;+ c = 0;+ for (pt++; isdigit(*pt) && *pt != '8' && *pt != '9'; pt++)+ {+ if (++i == 12)+ fprintf(outfile, "** Too many octal digits in \\o{...} item; "+ "using only the first twelve.\n");+ else c = c * 8 + *pt - '0';+ }+ if (*pt == '}') p = pt + 1;+ else fprintf(outfile, "** Missing } after \\o{ (assumed)\n");+ }+ break;++ case 'x':+ if (*p == '{')+ {+ uint8_t *pt = p;+ c = 0;++ /* We used to have "while (isxdigit(*(++pt)))" here, but it fails+ when isxdigit() is a macro that refers to its argument more than+ once. This is banned by the C Standard, but apparently happens in at+ least one MacOS environment. */++ for (pt++; isxdigit(*pt); pt++)+ {+ if (++i == 9)+ fprintf(outfile, "** Too many hex digits in \\x{...} item; "+ "using only the first eight.\n");+ else c = c * 16 + tolower(*pt) - ((isdigit(*pt))? '0' : 'a' - 10);+ }+ if (*pt == '}')+ {+ p = pt + 1;+ break;+ }+ /* Not correct form for \x{...}; fall through */+ }++ /* \x without {} always defines just one byte in 8-bit mode. This+ allows UTF-8 characters to be constructed byte by byte, and also allows+ invalid UTF-8 sequences to be made. Just copy the byte in UTF-8 mode.+ Otherwise, pass it down as data. */++ c = 0;+ while (i++ < 2 && isxdigit(*p))+ {+ c = c * 16 + tolower(*p) - ((isdigit(*p))? '0' : 'a' - 10);+ p++;+ }+#if defined SUPPORT_PCRE2_8+ if (utf && (test_mode == PCRE8_MODE))+ {+ *q8++ = c;+ continue;+ }+#endif+ break;++ case 0: /* \ followed by EOF allows for an empty line */+ p--;+ continue;++ case '=': /* \= terminates the data, starts modifiers */+ goto ENDSTRING;++ case '[': /* \[ introduces a replicated character sequence */+ if (start_rep != NULL)+ {+ fprintf(outfile, "** Nested replication is not supported\n");+ return PR_OK;+ }+ start_rep = CAST8VAR(q);+ continue;++ default:+ if (isalnum(c))+ {+ fprintf(outfile, "** Unrecognized escape sequence \"\\%c\"\n", c);+ return PR_OK;+ }+ }++ /* We now have a character value in c that may be greater than 255.+ In 8-bit mode we convert to UTF-8 if we are in UTF mode. Values greater+ than 127 in UTF mode must have come from \x{...} or octal constructs+ because values from \x.. get this far only in non-UTF mode. */++#ifdef SUPPORT_PCRE2_8+ if (test_mode == PCRE8_MODE)+ {+ if (utf)+ {+ if (c > 0x7fffffff)+ {+ fprintf(outfile, "** Character \\x{%x} is greater than 0x7fffffff "+ "and so cannot be converted to UTF-8\n", c);+ return PR_OK;+ }+ q8 += ord2utf8(c, q8);+ }+ else+ {+ if (c > 0xffu)+ {+ fprintf(outfile, "** Character \\x{%x} is greater than 255 "+ "and UTF-8 mode is not enabled.\n", c);+ fprintf(outfile, "** Truncation will probably give the wrong "+ "result.\n");+ }+ *q8++ = (uint8_t)c;+ }+ }+#endif+#ifdef SUPPORT_PCRE2_16+ if (test_mode == PCRE16_MODE)+ {+ if (utf)+ {+ if (c > 0x10ffffu)+ {+ fprintf(outfile, "** Failed: character \\x{%x} is greater than "+ "0x10ffff and so cannot be converted to UTF-16\n", c);+ return PR_OK;+ }+ else if (c >= 0x10000u)+ {+ c-= 0x10000u;+ *q16++ = 0xD800 | (c >> 10);+ *q16++ = 0xDC00 | (c & 0x3ff);+ }+ else+ *q16++ = c;+ }+ else+ {+ if (c > 0xffffu)+ {+ fprintf(outfile, "** Character \\x{%x} is greater than 0xffff "+ "and UTF-16 mode is not enabled.\n", c);+ fprintf(outfile, "** Truncation will probably give the wrong "+ "result.\n");+ }++ *q16++ = (uint16_t)c;+ }+ }+#endif+#ifdef SUPPORT_PCRE2_32+ if (test_mode == PCRE32_MODE)+ {+ *q32++ = c;+ }+#endif+ }++ENDSTRING:+SET(*q, 0);+len = CASTVAR(uint8_t *, q) - dbuffer; /* Length in bytes */+ulen = len/code_unit_size; /* Length in code units */+arg_ulen = ulen; /* Value to use in match arg */++/* If the string was terminated by \= we must now interpret modifiers. */++if (p[-1] != 0 && !decode_modifiers(p, CTX_DAT, NULL, &dat_datctl))+ return PR_OK;++/* Setting substitute_{skip,fail} implies a substitute callout. */++if (dat_datctl.substitute_skip != 0 || dat_datctl.substitute_stop != 0)+ dat_datctl.control2 |= CTL2_SUBSTITUTE_CALLOUT;++/* Check for mutually exclusive modifiers. At present, these are all in the+first control word. */++for (k = 0; k < sizeof(exclusive_dat_controls)/sizeof(uint32_t); k++)+ {+ c = dat_datctl.control & exclusive_dat_controls[k];+ if (c != 0 && c != (c & (~c+1)))+ {+ show_controls(c, 0, "** Not allowed together:");+ fprintf(outfile, "\n");+ return PR_OK;+ }+ }++if (pat_patctl.replacement[0] != 0)+ {+ if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CALLOUT) != 0 &&+ (dat_datctl.control & CTL_NULLCONTEXT) != 0)+ {+ fprintf(outfile, "** Replacement callouts are not supported with null_context.\n");+ return PR_OK;+ }++ if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)+ fprintf(outfile, "** Ignored with replacement text: allcaptures\n");+ }++/* Warn for modifiers that are ignored for DFA. */++if ((dat_datctl.control & CTL_DFA) != 0)+ {+ if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)+ fprintf(outfile, "** Ignored after DFA matching: allcaptures\n");+ }++/* We now have the subject in dbuffer, with len containing the byte length, and+ulen containing the code unit length, with a copy in arg_ulen for use in match+function arguments (this gets changed to PCRE2_ZERO_TERMINATED when the+zero_terminate modifier is present).++Move the data to the end of the buffer so that a read over the end can be+caught by valgrind or other means. If we have explicit valgrind support, mark+the unused start of the buffer unaddressable. If we are using the POSIX+interface, or testing zero-termination, we must include the terminating zero in+the usable data. */++c = code_unit_size * (((pat_patctl.control & CTL_POSIX) ++ (dat_datctl.control & CTL_ZERO_TERMINATE) != 0)? 1:0);+pp = memmove(dbuffer + dbuffer_size - len - c, dbuffer, len + c);+#ifdef SUPPORT_VALGRIND+ VALGRIND_MAKE_MEM_NOACCESS(dbuffer, dbuffer_size - (len + c));+#endif++/* Now pp points to the subject string. POSIX matching is only possible in+8-bit mode, and it does not support timing or other fancy features. Some were+checked at compile time, but we need to check the match-time settings here. */++#ifdef SUPPORT_PCRE2_8+if ((pat_patctl.control & CTL_POSIX) != 0)+ {+ int rc;+ int eflags = 0;+ regmatch_t *pmatch = NULL;+ const char *msg = "** Ignored with POSIX interface:";++ if (dat_datctl.cerror[0] != CFORE_UNSET || dat_datctl.cerror[1] != CFORE_UNSET)+ prmsg(&msg, "callout_error");+ if (dat_datctl.cfail[0] != CFORE_UNSET || dat_datctl.cfail[1] != CFORE_UNSET)+ prmsg(&msg, "callout_fail");+ if (dat_datctl.copy_numbers[0] >= 0 || dat_datctl.copy_names[0] != 0)+ prmsg(&msg, "copy");+ if (dat_datctl.get_numbers[0] >= 0 || dat_datctl.get_names[0] != 0)+ prmsg(&msg, "get");+ if (dat_datctl.jitstack != 0) prmsg(&msg, "jitstack");+ if (dat_datctl.offset != 0) prmsg(&msg, "offset");++ if ((dat_datctl.options & ~POSIX_SUPPORTED_MATCH_OPTIONS) != 0)+ {+ fprintf(outfile, "%s", msg);+ show_match_options(dat_datctl.options & ~POSIX_SUPPORTED_MATCH_OPTIONS);+ msg = "";+ }+ if ((dat_datctl.control & ~POSIX_SUPPORTED_MATCH_CONTROLS) != 0 ||+ (dat_datctl.control2 & ~POSIX_SUPPORTED_MATCH_CONTROLS2) != 0)+ {+ show_controls(dat_datctl.control & ~POSIX_SUPPORTED_MATCH_CONTROLS,+ dat_datctl.control2 & ~POSIX_SUPPORTED_MATCH_CONTROLS2, msg);+ msg = "";+ }++ if (msg[0] == 0) fprintf(outfile, "\n");++ if (dat_datctl.oveccount > 0)+ {+ pmatch = (regmatch_t *)malloc(sizeof(regmatch_t) * dat_datctl.oveccount);+ if (pmatch == NULL)+ {+ fprintf(outfile, "** Failed to get memory for recording matching "+ "information (size set = %du)\n", dat_datctl.oveccount);+ return PR_OK;+ }+ }++ if (dat_datctl.startend[0] != CFORE_UNSET)+ {+ pmatch[0].rm_so = dat_datctl.startend[0];+ pmatch[0].rm_eo = (dat_datctl.startend[1] != 0)?+ dat_datctl.startend[1] : len;+ eflags |= REG_STARTEND;+ }++ if ((dat_datctl.options & PCRE2_NOTBOL) != 0) eflags |= REG_NOTBOL;+ if ((dat_datctl.options & PCRE2_NOTEOL) != 0) eflags |= REG_NOTEOL;+ if ((dat_datctl.options & PCRE2_NOTEMPTY) != 0) eflags |= REG_NOTEMPTY;++ rc = regexec(&preg, (const char *)pp, dat_datctl.oveccount, pmatch, eflags);+ if (rc != 0)+ {+ (void)regerror(rc, &preg, (char *)pbuffer8, pbuffer8_size);+ fprintf(outfile, "No match: POSIX code %d: %s\n", rc, pbuffer8);+ }+ else if ((pat_patctl.control & CTL_POSIX_NOSUB) != 0)+ fprintf(outfile, "Matched with REG_NOSUB\n");+ else if (dat_datctl.oveccount == 0)+ fprintf(outfile, "Matched without capture\n");+ else+ {+ size_t i, j;+ size_t last_printed = (size_t)dat_datctl.oveccount;+ for (i = 0; i < (size_t)dat_datctl.oveccount; i++)+ {+ if (pmatch[i].rm_so >= 0)+ {+ PCRE2_SIZE start = pmatch[i].rm_so;+ PCRE2_SIZE end = pmatch[i].rm_eo;+ for (j = last_printed + 1; j < i; j++)+ fprintf(outfile, "%2d: <unset>\n", (int)j);+ last_printed = i;+ if (start > end)+ {+ start = pmatch[i].rm_eo;+ end = pmatch[i].rm_so;+ fprintf(outfile, "Start of matched string is beyond its end - "+ "displaying from end to start.\n");+ }+ fprintf(outfile, "%2d: ", (int)i);+ PCHARSV(pp, start, end - start, utf, outfile);+ fprintf(outfile, "\n");++ if ((i == 0 && (dat_datctl.control & CTL_AFTERTEXT) != 0) ||+ (dat_datctl.control & CTL_ALLAFTERTEXT) != 0)+ {+ fprintf(outfile, "%2d+ ", (int)i);+ /* Note: don't use the start/end variables here because we want to+ show the text from what is reported as the end. */+ PCHARSV(pp, pmatch[i].rm_eo, len - pmatch[i].rm_eo, utf, outfile);+ fprintf(outfile, "\n"); }+ }+ }+ }+ free(pmatch);+ return PR_OK;+ }+#endif /* SUPPORT_PCRE2_8 */++ /* Handle matching via the native interface. Check for consistency of+modifiers. */++if (dat_datctl.startend[0] != CFORE_UNSET)+ fprintf(outfile, "** \\=posix_startend ignored for non-POSIX matching\n");++/* ALLUSEDTEXT is not supported with JIT, but JIT is not used with DFA+matching, even if the JIT compiler was used. */++if ((dat_datctl.control & (CTL_ALLUSEDTEXT|CTL_DFA)) == CTL_ALLUSEDTEXT &&+ FLD(compiled_code, executable_jit) != NULL)+ {+ fprintf(outfile, "** Showing all consulted text is not supported by JIT: ignored\n");+ dat_datctl.control &= ~CTL_ALLUSEDTEXT;+ }++/* Handle passing the subject as zero-terminated. */++if ((dat_datctl.control & CTL_ZERO_TERMINATE) != 0)+ arg_ulen = PCRE2_ZERO_TERMINATED;++/* The nullcontext modifier is used to test calling pcre2_[jit_]match() with a+NULL context. */++use_dat_context = ((dat_datctl.control & CTL_NULLCONTEXT) != 0)?+ NULL : PTR(dat_context);++/* Enable display of malloc/free if wanted. We can do this only if either the+pattern or the subject is processed with a context. */++show_memory = (dat_datctl.control & CTL_MEMORY) != 0;++if (show_memory &&+ (pat_patctl.control & dat_datctl.control & CTL_NULLCONTEXT) != 0)+ fprintf(outfile, "** \\=memory requires either a pattern or a subject "+ "context: ignored\n");++/* Create and assign a JIT stack if requested. */++if (dat_datctl.jitstack != 0)+ {+ if (dat_datctl.jitstack != jit_stack_size)+ {+ PCRE2_JIT_STACK_FREE(jit_stack);+ PCRE2_JIT_STACK_CREATE(jit_stack, 1, dat_datctl.jitstack * 1024, NULL);+ jit_stack_size = dat_datctl.jitstack;+ }+ PCRE2_JIT_STACK_ASSIGN(dat_context, jit_callback, jit_stack);+ }++/* Or de-assign */++else if (jit_stack != NULL)+ {+ PCRE2_JIT_STACK_ASSIGN(dat_context, NULL, NULL);+ PCRE2_JIT_STACK_FREE(jit_stack);+ jit_stack = NULL;+ jit_stack_size = 0;+ }++/* When no JIT stack is assigned, we must ensure that there is a JIT callback+if we want to verify that JIT was actually used. */++if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_stack == NULL)+ {+ PCRE2_JIT_STACK_ASSIGN(dat_context, jit_callback, NULL);+ }++/* Adjust match_data according to size of offsets required. A size of zero+causes a new match data block to be obtained that exactly fits the pattern. */++if (dat_datctl.oveccount == 0)+ {+ PCRE2_MATCH_DATA_FREE(match_data);+ PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(match_data, compiled_code, NULL);+ PCRE2_GET_OVECTOR_COUNT(max_oveccount, match_data);+ }+else if (dat_datctl.oveccount <= max_oveccount)+ {+ SETFLD(match_data, oveccount, dat_datctl.oveccount);+ }+else+ {+ max_oveccount = dat_datctl.oveccount;+ PCRE2_MATCH_DATA_FREE(match_data);+ PCRE2_MATCH_DATA_CREATE(match_data, max_oveccount, NULL);+ }++if (CASTVAR(void *, match_data) == NULL)+ {+ fprintf(outfile, "** Failed to get memory for recording matching "+ "information (size requested: %d)\n", dat_datctl.oveccount);+ max_oveccount = 0;+ return PR_OK;+ }++ovector = FLD(match_data, ovector);+PCRE2_GET_OVECTOR_COUNT(oveccount, match_data);++/* Replacement processing is ignored for DFA matching. */++if (dat_datctl.replacement[0] != 0 && (dat_datctl.control & CTL_DFA) != 0)+ {+ fprintf(outfile, "** Ignored for DFA matching: replace\n");+ dat_datctl.replacement[0] = 0;+ }++/* If a replacement string is provided, call pcre2_substitute() instead of one+of the matching functions. First we have to convert the replacement string to+the appropriate width. */++if (dat_datctl.replacement[0] != 0)+ {+ int rc;+ uint8_t *pr;+ uint8_t rbuffer[REPLACE_BUFFSIZE];+ uint8_t nbuffer[REPLACE_BUFFSIZE];+ uint32_t xoptions;+ uint32_t emoption; /* External match option */+ PCRE2_SIZE j, rlen, nsize, erroroffset;+ BOOL badutf = FALSE;++#ifdef SUPPORT_PCRE2_8+ uint8_t *r8 = NULL;+#endif+#ifdef SUPPORT_PCRE2_16+ uint16_t *r16 = NULL;+#endif+#ifdef SUPPORT_PCRE2_32+ uint32_t *r32 = NULL;+#endif++ /* Fill the ovector with junk to detect elements that do not get set+ when they should be (relevant only when "allvector" is specified). */++ for (j = 0; j < 2*oveccount; j++) ovector[j] = JUNK_OFFSET;++ if (timeitm)+ fprintf(outfile, "** Timing is not supported with replace: ignored\n");++ if ((dat_datctl.control & CTL_ALTGLOBAL) != 0)+ fprintf(outfile, "** Altglobal is not supported with replace: ignored\n");++ /* Check for a test that does substitution after an initial external match.+ If this is set, we run the external match, but leave the interpretation of+ its output to pcre2_substitute(). */++ emoption = ((dat_datctl.control2 & CTL2_SUBSTITUTE_MATCHED) == 0)? 0 :+ PCRE2_SUBSTITUTE_MATCHED;++ if (emoption != 0)+ {+ PCRE2_MATCH(rc, compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options, match_data, use_dat_context);+ }++ xoptions = emoption |+ (((dat_datctl.control & CTL_GLOBAL) == 0)? 0 :+ PCRE2_SUBSTITUTE_GLOBAL) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_EXTENDED) == 0)? 0 :+ PCRE2_SUBSTITUTE_EXTENDED) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_LITERAL) == 0)? 0 :+ PCRE2_SUBSTITUTE_LITERAL) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_OVERFLOW_LENGTH) == 0)? 0 :+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_REPLACEMENT_ONLY) == 0)? 0 :+ PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_UNKNOWN_UNSET) == 0)? 0 :+ PCRE2_SUBSTITUTE_UNKNOWN_UNSET) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_UNSET_EMPTY) == 0)? 0 :+ PCRE2_SUBSTITUTE_UNSET_EMPTY);++ SETCASTPTR(r, rbuffer); /* Sets r8, r16, or r32, as appropriate. */+ pr = dat_datctl.replacement;++ /* If the replacement starts with '[<number>]' we interpret that as length+ value for the replacement buffer. */++ nsize = REPLACE_BUFFSIZE/code_unit_size;+ if (*pr == '[')+ {+ PCRE2_SIZE n = 0;+ while ((c = *(++pr)) >= CHAR_0 && c <= CHAR_9) n = n * 10 + c - CHAR_0;+ if (*pr++ != ']')+ {+ fprintf(outfile, "Bad buffer size in replacement string\n");+ return PR_OK;+ }+ if (n > nsize)+ {+ fprintf(outfile, "Replacement buffer setting (%" SIZ_FORM ") is too "+ "large (max %" SIZ_FORM ")\n", SIZ_CAST n, SIZ_CAST nsize);+ return PR_OK;+ }+ nsize = n;+ }++ /* Now copy the replacement string to a buffer of the appropriate width. No+ escape processing is done for replacements. In UTF mode, check for an invalid+ UTF-8 input string, and if it is invalid, just copy its code units without+ UTF interpretation. This provides a means of checking that an invalid string+ is detected. Otherwise, UTF-8 can be used to include wide characters in a+ replacement. */++ if (utf) badutf = valid_utf(pr, strlen((const char *)pr), &erroroffset);++ /* Not UTF or invalid UTF-8: just copy the code units. */++ if (!utf || badutf)+ {+ while ((c = *pr++) != 0)+ {+#ifdef SUPPORT_PCRE2_8+ if (test_mode == PCRE8_MODE) *r8++ = c;+#endif+#ifdef SUPPORT_PCRE2_16+ if (test_mode == PCRE16_MODE) *r16++ = c;+#endif+#ifdef SUPPORT_PCRE2_32+ if (test_mode == PCRE32_MODE) *r32++ = c;+#endif+ }+ }++ /* Valid UTF-8 replacement string */++ else while ((c = *pr++) != 0)+ {+ if (HASUTF8EXTRALEN(c)) { GETUTF8INC(c, pr); }++#ifdef SUPPORT_PCRE2_8+ if (test_mode == PCRE8_MODE) r8 += ord2utf8(c, r8);+#endif++#ifdef SUPPORT_PCRE2_16+ if (test_mode == PCRE16_MODE)+ {+ if (c >= 0x10000u)+ {+ c-= 0x10000u;+ *r16++ = 0xD800 | (c >> 10);+ *r16++ = 0xDC00 | (c & 0x3ff);+ }+ else *r16++ = c;+ }+#endif++#ifdef SUPPORT_PCRE2_32+ if (test_mode == PCRE32_MODE) *r32++ = c;+#endif+ }++ SET(*r, 0);+ if ((dat_datctl.control & CTL_ZERO_TERMINATE) != 0)+ rlen = PCRE2_ZERO_TERMINATED;+ else+ rlen = (CASTVAR(uint8_t *, r) - rbuffer)/code_unit_size;++ if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CALLOUT) != 0)+ {+ PCRE2_SET_SUBSTITUTE_CALLOUT(dat_context, substitute_callout_function, NULL);+ }+ else+ {+ PCRE2_SET_SUBSTITUTE_CALLOUT(dat_context, NULL, NULL); /* No callout */+ }++ PCRE2_SUBSTITUTE(rc, compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options|xoptions, match_data, use_dat_context,+ rbuffer, rlen, nbuffer, &nsize);++ if (rc < 0)+ {+ fprintf(outfile, "Failed: error %d", rc);+ if (rc != PCRE2_ERROR_NOMEMORY && nsize != PCRE2_UNSET)+ fprintf(outfile, " at offset %ld in replacement", (long int)nsize);+ fprintf(outfile, ": ");+ if (!print_error_message(rc, "", "")) return PR_ABEND;+ if (rc == PCRE2_ERROR_NOMEMORY &&+ (xoptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) != 0)+ fprintf(outfile, ": %ld code units are needed", (long int)nsize);+ }+ else+ {+ fprintf(outfile, "%2d: ", rc);+ PCHARSV(nbuffer, 0, nsize, utf, outfile);+ }++ fprintf(outfile, "\n");+ show_memory = FALSE;++ /* Show final ovector contents if requested. */++ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0)+ show_ovector(ovector, oveccount);++ return PR_OK;+ } /* End of substitution handling */++/* When a replacement string is not provided, run a loop for global matching+with one of the basic matching functions. For altglobal (or first time round+the loop), set an "unset" value for the previous match info. */++ovecsave[0] = ovecsave[1] = ovecsave[2] = PCRE2_UNSET;++for (gmatched = 0;; gmatched++)+ {+ PCRE2_SIZE j;+ int capcount;++ /* Fill the ovector with junk to detect elements that do not get set+ when they should be. */++ for (j = 0; j < 2*oveccount; j++) ovector[j] = JUNK_OFFSET;++ /* When matching is via pcre2_match(), we will detect the use of JIT via the+ stack callback function. */++ jit_was_used = (pat_patctl.control & CTL_JITFAST) != 0;++ /* Do timing if required. */++ if (timeitm > 0)+ {+ int i;+ clock_t start_time, time_taken;++ if ((dat_datctl.control & CTL_DFA) != 0)+ {+ if ((dat_datctl.options & PCRE2_DFA_RESTART) != 0)+ {+ fprintf(outfile, "Timing DFA restarts is not supported\n");+ return PR_OK;+ }+ if (dfa_workspace == NULL)+ dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));+ start_time = clock();+ for (i = 0; i < timeitm; i++)+ {+ PCRE2_DFA_MATCH(capcount, compiled_code, pp, arg_ulen,+ dat_datctl.offset, dat_datctl.options | g_notempty, match_data,+ use_dat_context, dfa_workspace, DFA_WS_DIMENSION);+ }+ }++ else if ((pat_patctl.control & CTL_JITFAST) != 0)+ {+ start_time = clock();+ for (i = 0; i < timeitm; i++)+ {+ PCRE2_JIT_MATCH(capcount, compiled_code, pp, arg_ulen,+ dat_datctl.offset, dat_datctl.options | g_notempty, match_data,+ use_dat_context);+ }+ }++ else+ {+ start_time = clock();+ for (i = 0; i < timeitm; i++)+ {+ PCRE2_MATCH(capcount, compiled_code, pp, arg_ulen,+ dat_datctl.offset, dat_datctl.options | g_notempty, match_data,+ use_dat_context);+ }+ }+ total_match_time += (time_taken = clock() - start_time);+ fprintf(outfile, "Match time %.4f milliseconds\n",+ (((double)time_taken * 1000.0) / (double)timeitm) /+ (double)CLOCKS_PER_SEC);+ }++ /* Find the heap, match and depth limits if requested. The depth and heap+ limits are not relevant for JIT. The return from check_match_limit() is the+ return from the final call to pcre2_match() or pcre2_dfa_match(). */++ if ((dat_datctl.control & CTL_FINDLIMITS) != 0)+ {+ capcount = 0; /* This stops compiler warnings */++ if (FLD(compiled_code, executable_jit) == NULL ||+ (dat_datctl.options & PCRE2_NO_JIT) != 0)+ {+ (void)check_match_limit(pp, arg_ulen, PCRE2_ERROR_HEAPLIMIT, "heap");+ }++ capcount = check_match_limit(pp, arg_ulen, PCRE2_ERROR_MATCHLIMIT,+ "match");++ if (FLD(compiled_code, executable_jit) == NULL ||+ (dat_datctl.options & PCRE2_NO_JIT) != 0 ||+ (dat_datctl.control & CTL_DFA) != 0)+ {+ capcount = check_match_limit(pp, arg_ulen, PCRE2_ERROR_DEPTHLIMIT,+ "depth");+ }++ if (capcount == 0)+ {+ fprintf(outfile, "Matched, but offsets vector is too small to show all matches\n");+ capcount = dat_datctl.oveccount;+ }+ }++ /* Otherwise just run a single match, setting up a callout if required (the+ default). There is a copy of the pattern in pbuffer8 for use by callouts. */++ else+ {+ if ((dat_datctl.control & CTL_CALLOUT_NONE) == 0)+ {+ PCRE2_SET_CALLOUT(dat_context, callout_function,+ (void *)(&dat_datctl.callout_data));+ first_callout = TRUE;+ last_callout_mark = NULL;+ callout_count = 0;+ }+ else+ {+ PCRE2_SET_CALLOUT(dat_context, NULL, NULL); /* No callout */+ }++ /* Run a single DFA or NFA match. */++ if ((dat_datctl.control & CTL_DFA) != 0)+ {+ if (dfa_workspace == NULL)+ dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));+ if (dfa_matched++ == 0)+ dfa_workspace[0] = -1; /* To catch bad restart */+ PCRE2_DFA_MATCH(capcount, compiled_code, pp, arg_ulen,+ dat_datctl.offset, dat_datctl.options | g_notempty, match_data,+ use_dat_context, dfa_workspace, DFA_WS_DIMENSION);+ if (capcount == 0)+ {+ fprintf(outfile, "Matched, but offsets vector is too small to show all matches\n");+ capcount = dat_datctl.oveccount;+ }+ }+ else+ {+ if ((pat_patctl.control & CTL_JITFAST) != 0)+ PCRE2_JIT_MATCH(capcount, compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options | g_notempty, match_data, use_dat_context);+ else+ PCRE2_MATCH(capcount, compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options | g_notempty, match_data, use_dat_context);+ if (capcount == 0)+ {+ fprintf(outfile, "Matched, but too many substrings\n");+ capcount = dat_datctl.oveccount;+ }+ }+ }++ /* The result of the match is now in capcount. First handle a successful+ match. */++ if (capcount >= 0)+ {+ int i;++ if (capcount > (int)oveccount) /* Check for lunatic return value */+ {+ fprintf(outfile,+ "** PCRE2 error: returned count %d is too big for ovector count %d\n",+ capcount, oveccount);+ capcount = oveccount;+ if ((dat_datctl.control & CTL_ANYGLOB) != 0)+ {+ fprintf(outfile, "** Global loop abandoned\n");+ dat_datctl.control &= ~CTL_ANYGLOB; /* Break g/G loop */+ }+ }++ /* If PCRE2_COPY_MATCHED_SUBJECT was set, check that things are as they+ should be, but not for fast JIT, where it isn't supported. */++ if ((dat_datctl.options & PCRE2_COPY_MATCHED_SUBJECT) != 0 &&+ (pat_patctl.control & CTL_JITFAST) == 0)+ {+ if ((FLD(match_data, flags) & PCRE2_MD_COPIED_SUBJECT) == 0)+ fprintf(outfile,+ "** PCRE2 error: flag not set after copy_matched_subject\n");++ if (CASTFLD(void *, match_data, subject) == pp)+ fprintf(outfile,+ "** PCRE2 error: copy_matched_subject has not copied\n");++ if (memcmp(CASTFLD(void *, match_data, subject), pp, ulen) != 0)+ fprintf(outfile,+ "** PCRE2 error: copy_matched_subject mismatch\n");+ }++ /* If this is not the first time round a global loop, check that the+ returned string has changed. If it has not, check for an empty string match+ at different starting offset from the previous match. This is a failed test+ retry for null-matching patterns that don't match at their starting offset,+ for example /(?<=\G.)/. A repeated match at the same point is not such a+ pattern, and must be discarded, and we then proceed to seek a non-null+ match at the current point. For any other repeated match, there is a bug+ somewhere and we must break the loop because it will go on for ever. We+ know that there are always at least two elements in the ovector. */++ if (gmatched > 0 && ovecsave[0] == ovector[0] && ovecsave[1] == ovector[1])+ {+ if (ovector[0] == ovector[1] && ovecsave[2] != dat_datctl.offset)+ {+ g_notempty = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;+ ovecsave[2] = dat_datctl.offset;+ continue; /* Back to the top of the loop */+ }+ fprintf(outfile,+ "** PCRE2 error: global repeat returned the same string as previous\n");+ fprintf(outfile, "** Global loop abandoned\n");+ dat_datctl.control &= ~CTL_ANYGLOB; /* Break g/G loop */+ }++ /* "allcaptures" requests showing of all captures in the pattern, to check+ unset ones at the end. It may be set on the pattern or the data. Implement+ by setting capcount to the maximum. This is not relevant for DFA matching,+ so ignore it (warning given above). */++ if ((dat_datctl.control & (CTL_ALLCAPTURES|CTL_DFA)) == CTL_ALLCAPTURES)+ {+ capcount = maxcapcount + 1; /* Allow for full match */+ if (capcount > (int)oveccount) capcount = oveccount;+ }++ /* "allvector" request showing the entire ovector. */++ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0) capcount = oveccount;++ /* Output the captured substrings. Note that, for the matched string,+ the use of \K in an assertion can make the start later than the end. */++ for (i = 0; i < 2*capcount; i += 2)+ {+ PCRE2_SIZE lleft, lmiddle, lright;+ PCRE2_SIZE start = ovector[i];+ PCRE2_SIZE end = ovector[i+1];++ if (start > end)+ {+ start = ovector[i+1];+ end = ovector[i];+ fprintf(outfile, "Start of matched string is beyond its end - "+ "displaying from end to start.\n");+ }++ fprintf(outfile, "%2d: ", i/2);++ /* Check for an unset group */++ if (start == PCRE2_UNSET && end == PCRE2_UNSET)+ {+ fprintf(outfile, "<unset>\n");+ continue;+ }++ /* Check for silly offsets, in particular, values that have not been+ set when they should have been. However, if we are past the end of the+ captures for this pattern ("allvector" causes this), or if we are DFA+ matching, it isn't an error if the entry is unchanged. */++ if (start > ulen || end > ulen)+ {+ if (((dat_datctl.control & CTL_DFA) != 0 ||+ i >= (int)(2*maxcapcount + 2)) &&+ start == JUNK_OFFSET && end == JUNK_OFFSET)+ fprintf(outfile, "<unchanged>\n");+ else+ fprintf(outfile, "ERROR: bad value(s) for offset(s): 0x%lx 0x%lx\n",+ (unsigned long int)start, (unsigned long int)end);+ continue;+ }++ /* When JIT is not being used, ALLUSEDTEXT may be set. (It if is set with+ JIT, it is disabled above, with a comment.) When the match is done by the+ interpreter, leftchar and rightchar are available, and if ALLUSEDTEXT is+ set, and if the leftmost consulted character is before the start of the+ match or the rightmost consulted character is past the end of the match,+ we want to show all consulted characters for the main matched string, and+ indicate which were lookarounds. */++ if (i == 0)+ {+ BOOL showallused;+ PCRE2_SIZE leftchar, rightchar;++ if ((dat_datctl.control & CTL_ALLUSEDTEXT) != 0)+ {+ leftchar = FLD(match_data, leftchar);+ rightchar = FLD(match_data, rightchar);+ showallused = i == 0 && (leftchar < start || rightchar > end);+ }+ else showallused = FALSE;++ if (showallused)+ {+ PCHARS(lleft, pp, leftchar, start - leftchar, utf, outfile);+ PCHARS(lmiddle, pp, start, end - start, utf, outfile);+ PCHARS(lright, pp, end, rightchar - end, utf, outfile);+ if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)+ fprintf(outfile, " (JIT)");+ fprintf(outfile, "\n ");+ for (j = 0; j < lleft; j++) fprintf(outfile, "<");+ for (j = 0; j < lmiddle; j++) fprintf(outfile, " ");+ for (j = 0; j < lright; j++) fprintf(outfile, ">");+ }++ /* When a pattern contains \K, the start of match position may be+ different to the start of the matched string. When this is the case,+ show it when requested. */++ else if ((dat_datctl.control & CTL_STARTCHAR) != 0)+ {+ PCRE2_SIZE startchar;+ PCRE2_GET_STARTCHAR(startchar, match_data);+ PCHARS(lleft, pp, startchar, start - startchar, utf, outfile);+ PCHARSV(pp, start, end - start, utf, outfile);+ if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)+ fprintf(outfile, " (JIT)");+ if (startchar != start)+ {+ fprintf(outfile, "\n ");+ for (j = 0; j < lleft; j++) fprintf(outfile, "^");+ }+ }++ /* Otherwise, just show the matched string. */++ else+ {+ PCHARSV(pp, start, end - start, utf, outfile);+ if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)+ fprintf(outfile, " (JIT)");+ }+ }++ /* Not the main matched string. Just show it unadorned. */++ else+ {+ PCHARSV(pp, start, end - start, utf, outfile);+ }++ fprintf(outfile, "\n");++ /* Note: don't use the start/end variables here because we want to+ show the text from what is reported as the end. */++ if ((dat_datctl.control & CTL_ALLAFTERTEXT) != 0 ||+ (i == 0 && (dat_datctl.control & CTL_AFTERTEXT) != 0))+ {+ fprintf(outfile, "%2d+ ", i/2);+ PCHARSV(pp, ovector[i+1], ulen - ovector[i+1], utf, outfile);+ fprintf(outfile, "\n");+ }+ }++ /* Output (*MARK) data if requested */++ if ((dat_datctl.control & CTL_MARK) != 0 &&+ TESTFLD(match_data, mark, !=, NULL))+ {+ fprintf(outfile, "MK: ");+ PCHARSV(CASTFLD(void *, match_data, mark), -1, -1, utf, outfile);+ fprintf(outfile, "\n");+ }++ /* Process copy/get strings */++ if (!copy_and_get(utf, capcount)) return PR_ABEND;++ } /* End of handling a successful match */++ /* There was a partial match. The value of ovector[0] is the bumpalong point,+ that is, startchar, not any \K point that might have been passed. When JIT is+ not in use, "allusedtext" may be set, in which case we indicate the leftmost+ consulted character. */++ else if (capcount == PCRE2_ERROR_PARTIAL)+ {+ PCRE2_SIZE leftchar;+ int backlength;+ int rubriclength = 0;++ if ((dat_datctl.control & CTL_ALLUSEDTEXT) != 0)+ {+ leftchar = FLD(match_data, leftchar);+ }+ else leftchar = ovector[0];++ fprintf(outfile, "Partial match");+ if ((dat_datctl.control & CTL_MARK) != 0 &&+ TESTFLD(match_data, mark, !=, NULL))+ {+ fprintf(outfile, ", mark=");+ PCHARS(rubriclength, CASTFLD(void *, match_data, mark), -1, -1, utf,+ outfile);+ rubriclength += 7;+ }+ fprintf(outfile, ": ");+ rubriclength += 15;++ PCHARS(backlength, pp, leftchar, ovector[0] - leftchar, utf, outfile);+ PCHARSV(pp, ovector[0], ulen - ovector[0], utf, outfile);++ if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)+ fprintf(outfile, " (JIT)");+ fprintf(outfile, "\n");++ if (backlength != 0)+ {+ int i;+ for (i = 0; i < rubriclength; i++) fprintf(outfile, " ");+ for (i = 0; i < backlength; i++) fprintf(outfile, "<");+ fprintf(outfile, "\n");+ }++ if (ulen != ovector[1])+ fprintf(outfile, "** ovector[1] is not equal to the subject length: "+ "%ld != %ld\n", (unsigned long int)ovector[1], (unsigned long int)ulen);++ /* Process copy/get strings */++ if (!copy_and_get(utf, 1)) return PR_ABEND;++ /* "allvector" outputs the entire vector */++ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0)+ show_ovector(ovector, oveccount);++ break; /* Out of the /g loop */+ } /* End of handling partial match */++ /* Failed to match. If this is a /g or /G loop, we might previously have+ set g_notempty (to PCRE2_NOTEMPTY_ATSTART|PCRE2_ANCHORED) after a null match.+ If that is the case, this is not necessarily the end. We want to advance the+ start offset, and continue. We won't be at the end of the string - that was+ checked before setting g_notempty. We achieve the effect by pretending that a+ single character was matched.++ Complication arises in the case when the newline convention is "any", "crlf",+ or "anycrlf". If the previous match was at the end of a line terminated by+ CRLF, an advance of one character just passes the CR, whereas we should+ prefer the longer newline sequence, as does the code in pcre2_match().++ Otherwise, in the case of UTF-8 or UTF-16 matching, the advance must be one+ character, not one byte. */++ else if (g_notempty != 0) /* There was a previous null match */+ {+ uint16_t nl = FLD(compiled_code, newline_convention);+ PCRE2_SIZE start_offset = dat_datctl.offset; /* Where the match was */+ PCRE2_SIZE end_offset = start_offset + 1;++ if ((nl == PCRE2_NEWLINE_CRLF || nl == PCRE2_NEWLINE_ANY ||+ nl == PCRE2_NEWLINE_ANYCRLF) &&+ start_offset < ulen - 1 &&+ CODE_UNIT(pp, start_offset) == '\r' &&+ CODE_UNIT(pp, end_offset) == '\n')+ end_offset++;++ else if (utf && test_mode != PCRE32_MODE)+ {+ if (test_mode == PCRE8_MODE)+ {+ for (; end_offset < ulen; end_offset++)+ if ((((PCRE2_SPTR8)pp)[end_offset] & 0xc0) != 0x80) break;+ }+ else /* 16-bit mode */+ {+ for (; end_offset < ulen; end_offset++)+ if ((((PCRE2_SPTR16)pp)[end_offset] & 0xfc00) != 0xdc00) break;+ }+ }++ SETFLDVEC(match_data, ovector, 0, start_offset);+ SETFLDVEC(match_data, ovector, 1, end_offset);+ } /* End of handling null match in a global loop */++ /* A "normal" match failure. There will be a negative error number in+ capcount. */++ else+ {+ switch(capcount)+ {+ case PCRE2_ERROR_NOMATCH:+ if (gmatched == 0)+ {+ fprintf(outfile, "No match");+ if ((dat_datctl.control & CTL_MARK) != 0 &&+ TESTFLD(match_data, mark, !=, NULL))+ {+ fprintf(outfile, ", mark = ");+ PCHARSV(CASTFLD(void *, match_data, mark), -1, -1, utf, outfile);+ }+ if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)+ fprintf(outfile, " (JIT)");+ fprintf(outfile, "\n");++ /* "allvector" outputs the entire vector */++ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0)+ show_ovector(ovector, oveccount);+ }+ break;++ case PCRE2_ERROR_BADUTFOFFSET:+ fprintf(outfile, "Error %d (bad UTF-%d offset)\n", capcount, test_mode);+ break;++ default:+ fprintf(outfile, "Failed: error %d: ", capcount);+ if (!print_error_message(capcount, "", "")) return PR_ABEND;+ if (capcount <= PCRE2_ERROR_UTF8_ERR1 &&+ capcount >= PCRE2_ERROR_UTF32_ERR2)+ {+ PCRE2_SIZE startchar;+ PCRE2_GET_STARTCHAR(startchar, match_data);+ fprintf(outfile, " at offset %" SIZ_FORM, SIZ_CAST startchar);+ }+ fprintf(outfile, "\n");+ break;+ }++ break; /* Out of the /g loop */+ } /* End of failed match handling */++ /* Control reaches here in two circumstances: (a) after a match, and (b)+ after a non-match that immediately followed a match on an empty string when+ doing a global search. Such a match is done with PCRE2_NOTEMPTY_ATSTART and+ PCRE2_ANCHORED set in g_notempty. The code above turns it into a fake match+ of one character. So effectively we get here only after a match. If we+ are not doing a global search, we are done. */++ if ((dat_datctl.control & CTL_ANYGLOB) == 0) break; else+ {+ PCRE2_SIZE match_offset = FLD(match_data, ovector)[0];+ PCRE2_SIZE end_offset = FLD(match_data, ovector)[1];++ /* We must now set up for the next iteration of a global search. If we have+ matched an empty string, first check to see if we are at the end of the+ subject. If so, the loop is over. Otherwise, mimic what Perl's /g option+ does. Set PCRE2_NOTEMPTY_ATSTART and PCRE2_ANCHORED and try the match again+ at the same point. If this fails it will be picked up above, where a fake+ match is set up so that at this point we advance to the next character.++ However, in order to cope with patterns that never match at their starting+ offset (e.g. /(?<=\G.)/) we don't do this when the match offset is greater+ than the starting offset. This means there will be a retry with the+ starting offset at the match offset. If this returns the same match again,+ it is picked up above and ignored, and the special action is then taken. */++ if (match_offset == end_offset)+ {+ if (end_offset == ulen) break; /* End of subject */+ if (match_offset <= dat_datctl.offset)+ g_notempty = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;+ }++ /* However, even after matching a non-empty string, there is still one+ tricky case. If a pattern contains \K within a lookbehind assertion at the+ start, the end of the matched string can be at the offset where the match+ started. In the case of a normal /g iteration without special action, this+ leads to a loop that keeps on returning the same substring. The loop would+ be caught above, but we really want to move on to the next match. */++ else+ {+ g_notempty = 0; /* Set for a "normal" repeat */+ if ((dat_datctl.control & CTL_GLOBAL) != 0)+ {+ PCRE2_SIZE startchar;+ PCRE2_GET_STARTCHAR(startchar, match_data);+ if (end_offset <= startchar)+ {+ if (startchar >= ulen) break; /* End of subject */+ end_offset = startchar + 1;+ if (utf && test_mode != PCRE32_MODE)+ {+ if (test_mode == PCRE8_MODE)+ {+ for (; end_offset < ulen; end_offset++)+ if ((((PCRE2_SPTR8)pp)[end_offset] & 0xc0) != 0x80) break;+ }+ else /* 16-bit mode */+ {+ for (; end_offset < ulen; end_offset++)+ if ((((PCRE2_SPTR16)pp)[end_offset] & 0xfc00) != 0xdc00) break;+ }+ }+ }+ }+ }++ /* For a normal global (/g) iteration, save the current ovector[0,1] and+ the starting offset so that we can check that they do change each time.+ Otherwise a matching bug that returns the same string causes an infinite+ loop. It has happened! Then update the start offset, leaving other+ parameters alone. */++ if ((dat_datctl.control & CTL_GLOBAL) != 0)+ {+ ovecsave[0] = ovector[0];+ ovecsave[1] = ovector[1];+ ovecsave[2] = dat_datctl.offset;+ dat_datctl.offset = end_offset;+ }++ /* For altglobal, just update the pointer and length. */++ else+ {+ pp += end_offset * code_unit_size;+ len -= end_offset * code_unit_size;+ ulen -= end_offset;+ if (arg_ulen != PCRE2_ZERO_TERMINATED) arg_ulen -= end_offset;+ }+ }+ } /* End of global loop */++show_memory = FALSE;+return PR_OK;+}+++++/*************************************************+* Print PCRE2 version *+*************************************************/++static void+print_version(FILE *f)+{+VERSION_TYPE *vp;+fprintf(f, "PCRE2 version ");+for (vp = version; *vp != 0; vp++) fprintf(f, "%c", *vp);+fprintf(f, "\n");+}++++/*************************************************+* Print Unicode version *+*************************************************/++static void+print_unicode_version(FILE *f)+{+VERSION_TYPE *vp;+fprintf(f, "Unicode version ");+for (vp = uversion; *vp != 0; vp++) fprintf(f, "%c", *vp);+}++++/*************************************************+* Print JIT target *+*************************************************/++static void+print_jit_target(FILE *f)+{+VERSION_TYPE *vp;+for (vp = jittarget; *vp != 0; vp++) fprintf(f, "%c", *vp);+}++++/*************************************************+* Print newline configuration *+*************************************************/++/* Output is always to stdout.++Arguments:+ rc the return code from PCRE2_CONFIG_NEWLINE+ isc TRUE if called from "-C newline"+Returns: nothing+*/++static void+print_newline_config(uint32_t optval, BOOL isc)+{+if (!isc) printf(" Default newline sequence is ");+if (optval < sizeof(newlines)/sizeof(char *))+ printf("%s\n", newlines[optval]);+else+ printf("a non-standard value: %d\n", optval);+}++++/*************************************************+* Usage function *+*************************************************/++static void+usage(void)+{+printf("Usage: pcre2test [options] [<input file> [<output file>]]\n\n");+printf("Input and output default to stdin and stdout.\n");+#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+printf("If input is a terminal, readline() is used to read from it.\n");+#else+printf("This version of pcre2test is not linked with readline().\n");+#endif+printf("\nOptions:\n");+#ifdef SUPPORT_PCRE2_8+printf(" -8 use the 8-bit library\n");+#endif+#ifdef SUPPORT_PCRE2_16+printf(" -16 use the 16-bit library\n");+#endif+#ifdef SUPPORT_PCRE2_32+printf(" -32 use the 32-bit library\n");+#endif+printf(" -ac set default pattern modifier PCRE2_AUTO_CALLOUT\n");+printf(" -AC as -ac, but also set subject 'callout_extra' modifier\n");+printf(" -b set default pattern modifier 'fullbincode'\n");+printf(" -C show PCRE2 compile-time options and exit\n");+printf(" -C arg show a specific compile-time option and exit with its\n");+printf(" value if numeric (else 0). The arg can be:\n");+printf(" backslash-C use of \\C is enabled [0, 1]\n");+printf(" bsr \\R type [ANYCRLF, ANY]\n");+printf(" ebcdic compiled for EBCDIC character code [0,1]\n");+printf(" ebcdic-nl NL code if compiled for EBCDIC\n");+printf(" jit just-in-time compiler supported [0, 1]\n");+printf(" linksize internal link size [2, 3, 4]\n");+printf(" newline newline type [CR, LF, CRLF, ANYCRLF, ANY, NUL]\n");+printf(" pcre2-8 8 bit library support enabled [0, 1]\n");+printf(" pcre2-16 16 bit library support enabled [0, 1]\n");+printf(" pcre2-32 32 bit library support enabled [0, 1]\n");+printf(" unicode Unicode and UTF support enabled [0, 1]\n");+printf(" -d set default pattern modifier 'debug'\n");+printf(" -dfa set default subject modifier 'dfa'\n");+printf(" -error <n,m,..> show messages for error numbers, then exit\n");+printf(" -help show usage information\n");+printf(" -i set default pattern modifier 'info'\n");+printf(" -jit set default pattern modifier 'jit'\n");+printf(" -jitfast set default pattern modifier 'jitfast'\n");+printf(" -jitverify set default pattern modifier 'jitverify'\n");+printf(" -LM list pattern and subject modifiers, then exit\n");+printf(" -q quiet: do not output PCRE2 version number at start\n");+printf(" -pattern <s> set default pattern modifier fields\n");+printf(" -subject <s> set default subject modifier fields\n");+printf(" -S <n> set stack size to <n> mebibytes\n");+printf(" -t [<n>] time compilation and execution, repeating <n> times\n");+printf(" -tm [<n>] time execution (matching) only, repeating <n> times\n");+printf(" -T same as -t, but show total times at the end\n");+printf(" -TM same as -tm, but show total time at the end\n");+printf(" -version show PCRE2 version and exit\n");+}++++/*************************************************+* Handle -C option *+*************************************************/++/* This option outputs configuration options and sets an appropriate return+code when asked for a single option. The code is abstracted into a separate+function because of its size. Use whichever pcre2_config() function is+available.++Argument: an option name or NULL+Returns: the return code+*/++static int+c_option(const char *arg)+{+uint32_t optval;+unsigned int i = COPTLISTCOUNT;+int yield = 0;++if (arg != NULL && arg[0] != CHAR_MINUS)+ {+ for (i = 0; i < COPTLISTCOUNT; i++)+ if (strcmp(arg, coptlist[i].name) == 0) break;++ if (i >= COPTLISTCOUNT)+ {+ fprintf(stderr, "** Unknown -C option '%s'\n", arg);+ return 0;+ }++ switch (coptlist[i].type)+ {+ case CONF_BSR:+ (void)PCRE2_CONFIG(coptlist[i].value, &optval);+ printf("%s\n", (optval == PCRE2_BSR_ANYCRLF)? "ANYCRLF" : "ANY");+ break;++ case CONF_FIX:+ yield = coptlist[i].value;+ printf("%d\n", yield);+ break;++ case CONF_FIZ:+ optval = coptlist[i].value;+ printf("%d\n", optval);+ break;++ case CONF_INT:+ (void)PCRE2_CONFIG(coptlist[i].value, &yield);+ printf("%d\n", yield);+ break;++ case CONF_NL:+ (void)PCRE2_CONFIG(coptlist[i].value, &optval);+ print_newline_config(optval, TRUE);+ break;+ }++/* For VMS, return the value by setting a symbol, for certain values only. This+is contributed code which the PCRE2 developers have no means of testing. */++#ifdef __VMS++/* This is the original code provided by the first VMS contributor. */+#ifdef NEVER+ if (copytlist[i].type == CONF_FIX || coptlist[i].type == CONF_INT)+ {+ char ucname[16];+ strcpy(ucname, coptlist[i].name);+ for (i = 0; ucname[i] != 0; i++) ucname[i] = toupper[ucname[i]];+ vms_setsymbol(ucname, 0, optval);+ }+#endif++/* This is the new code, provided by a second VMS contributor. */++ if (coptlist[i].type == CONF_FIX || coptlist[i].type == CONF_INT)+ {+ char nam_buf[22], val_buf[4];+ $DESCRIPTOR(nam, nam_buf);+ $DESCRIPTOR(val, val_buf);++ strcpy(nam_buf, coptlist[i].name);+ nam.dsc$w_length = strlen(nam_buf);+ sprintf(val_buf, "%d", yield);+ val.dsc$w_length = strlen(val_buf);+ lib$set_symbol(&nam, &val);+ }+#endif /* __VMS */++ return yield;+ }++/* No argument for -C: output all configuration information. */++print_version(stdout);+printf("Compiled with\n");++#ifdef EBCDIC+printf(" EBCDIC code support: LF is 0x%02x\n", CHAR_LF);+#if defined NATIVE_ZOS+printf(" EBCDIC code page %s or similar\n", pcrz_cpversion());+#endif+#endif++(void)PCRE2_CONFIG(PCRE2_CONFIG_COMPILED_WIDTHS, &optval);+if (optval & 1) printf(" 8-bit support\n");+if (optval & 2) printf(" 16-bit support\n");+if (optval & 4) printf(" 32-bit support\n");++#ifdef SUPPORT_VALGRIND+printf(" Valgrind support\n");+#endif++(void)PCRE2_CONFIG(PCRE2_CONFIG_UNICODE, &optval);+if (optval != 0)+ {+ printf(" UTF and UCP support (");+ print_unicode_version(stdout);+ printf(")\n");+ }+else printf(" No Unicode support\n");++(void)PCRE2_CONFIG(PCRE2_CONFIG_JIT, &optval);+if (optval != 0)+ {+ printf(" Just-in-time compiler support: ");+ print_jit_target(stdout);+ printf("\n");+ }+else+ {+ printf(" No just-in-time compiler support\n");+ }++(void)PCRE2_CONFIG(PCRE2_CONFIG_NEWLINE, &optval);+print_newline_config(optval, FALSE);+(void)PCRE2_CONFIG(PCRE2_CONFIG_BSR, &optval);+printf(" \\R matches %s\n",+ (optval == PCRE2_BSR_ANYCRLF)? "CR, LF, or CRLF only" :+ "all Unicode newlines");+(void)PCRE2_CONFIG(PCRE2_CONFIG_NEVER_BACKSLASH_C, &optval);+printf(" \\C is %ssupported\n", optval? "not ":"");+(void)PCRE2_CONFIG(PCRE2_CONFIG_LINKSIZE, &optval);+printf(" Internal link size = %d\n", optval);+(void)PCRE2_CONFIG(PCRE2_CONFIG_PARENSLIMIT, &optval);+printf(" Parentheses nest limit = %d\n", optval);+(void)PCRE2_CONFIG(PCRE2_CONFIG_HEAPLIMIT, &optval);+printf(" Default heap limit = %d kibibytes\n", optval);+(void)PCRE2_CONFIG(PCRE2_CONFIG_MATCHLIMIT, &optval);+printf(" Default match limit = %d\n", optval);+(void)PCRE2_CONFIG(PCRE2_CONFIG_DEPTHLIMIT, &optval);+printf(" Default depth limit = %d\n", optval);++#if defined SUPPORT_LIBREADLINE+printf(" pcre2test has libreadline support\n");+#elif defined SUPPORT_LIBEDIT+printf(" pcre2test has libedit support\n");+#else+printf(" pcre2test has neither libreadline nor libedit support\n");+#endif++return 0;+}++++/*************************************************+* Display one modifier *+*************************************************/++static void+display_one_modifier(modstruct *m, BOOL for_pattern)+{+uint32_t c = (!for_pattern && (m->which == MOD_PND || m->which == MOD_PNDP))?+ '*' : ' ';+printf("%c%s", c, m->name);+}++++/*************************************************+* Display pattern or subject modifiers *+*************************************************/++/* In order to print in two columns, first scan without printing to get a list+of the modifiers that are required.++Arguments:+ for_pattern TRUE for pattern modifiers, FALSE for subject modifiers+ title string to be used in title++Returns: nothing+*/++static void+display_selected_modifiers(BOOL for_pattern, const char *title)+{+uint32_t i, j;+uint32_t n = 0;+uint32_t list[MODLISTCOUNT];++for (i = 0; i < MODLISTCOUNT; i++)+ {+ BOOL is_pattern = TRUE;+ modstruct *m = modlist + i;++ switch (m->which)+ {+ case MOD_CTC: /* Compile context */+ case MOD_PAT: /* Pattern */+ case MOD_PATP: /* Pattern, OK for Perl-compatible test */+ break;++ /* The MOD_PND and MOD_PNDP modifiers are precisely those that affect+ subjects, but can be given with a pattern. We list them as subject+ modifiers, but marked with an asterisk.*/++ case MOD_CTM: /* Match context */+ case MOD_DAT: /* Subject line */+ case MOD_PND: /* As PD, but not default pattern */+ case MOD_PNDP: /* As PND, OK for Perl-compatible test */+ is_pattern = FALSE;+ break;++ default: printf("** Unknown type for modifier '%s'\n", m->name);+ /* Fall through */+ case MOD_PD: /* Pattern or subject */+ case MOD_PDP: /* As PD, OK for Perl-compatible test */+ is_pattern = for_pattern;+ break;+ }++ if (for_pattern == is_pattern) list[n++] = i;+ }++/* Now print from the list in two columns. */++printf("-------------- %s MODIFIERS --------------\n", title);++for (i = 0, j = (n+1)/2; i < (n+1)/2; i++, j++)+ {+ modstruct *m = modlist + list[i];+ display_one_modifier(m, for_pattern);+ if (j < n)+ {+ uint32_t k = 27 - strlen(m->name);+ while (k-- > 0) printf(" ");+ display_one_modifier(modlist + list[j], for_pattern);+ }+ printf("\n");+ }+}++++/*************************************************+* Display the list of modifiers *+*************************************************/++static void+display_modifiers(void)+{+printf(+ "An asterisk on a subject modifier means that it may be given on a pattern\n"+ "line, in order to apply to all subjects matched by that pattern. Modifiers\n"+ "that are listed for both patterns and subjects have different effects in\n"+ "each case.\n\n");+display_selected_modifiers(TRUE, "PATTERN");+printf("\n");+display_selected_modifiers(FALSE, "SUBJECT");+}++++/*************************************************+* Main Program *+*************************************************/++int+main(int argc, char **argv)+{+uint32_t temp;+uint32_t yield = 0;+uint32_t op = 1;+BOOL notdone = TRUE;+BOOL quiet = FALSE;+BOOL showtotaltimes = FALSE;+BOOL skipping = FALSE;+char *arg_subject = NULL;+char *arg_pattern = NULL;+char *arg_error = NULL;++/* The offsets to the options and control bits fields of the pattern and data+control blocks must be the same so that common options and controls such as+"anchored" or "memory" can work for either of them from a single table entry.+We cannot test this till runtime because "offsetof" does not work in the+preprocessor. */++if (PO(options) != DO(options) || PO(control) != DO(control) ||+ PO(control2) != DO(control2))+ {+ fprintf(stderr, "** Coding error: "+ "options and control offsets for pattern and data must be the same.\n");+ return 1;+ }++/* Get the PCRE2 and Unicode version number and JIT target information, at the+same time checking that a request for the length gives the same answer. Also+check lengths for non-string items. */++if (PCRE2_CONFIG(PCRE2_CONFIG_VERSION, NULL) !=+ PCRE2_CONFIG(PCRE2_CONFIG_VERSION, version) ||++ PCRE2_CONFIG(PCRE2_CONFIG_UNICODE_VERSION, NULL) !=+ PCRE2_CONFIG(PCRE2_CONFIG_UNICODE_VERSION, uversion) ||++ PCRE2_CONFIG(PCRE2_CONFIG_JITTARGET, NULL) !=+ PCRE2_CONFIG(PCRE2_CONFIG_JITTARGET, jittarget) ||++ PCRE2_CONFIG(PCRE2_CONFIG_UNICODE, NULL) != sizeof(uint32_t) ||+ PCRE2_CONFIG(PCRE2_CONFIG_MATCHLIMIT, NULL) != sizeof(uint32_t))+ {+ fprintf(stderr, "** Error in pcre2_config(): bad length\n");+ return 1;+ }++/* Check that bad options are diagnosed. */++if (PCRE2_CONFIG(999, NULL) != PCRE2_ERROR_BADOPTION ||+ PCRE2_CONFIG(999, &temp) != PCRE2_ERROR_BADOPTION)+ {+ fprintf(stderr, "** Error in pcre2_config(): bad option not diagnosed\n");+ return 1;+ }++/* This configuration option is now obsolete, but running a quick check ensures+that its code is covered. */++(void)PCRE2_CONFIG(PCRE2_CONFIG_STACKRECURSE, &temp);++/* Get buffers from malloc() so that valgrind will check their misuse when+debugging. They grow automatically when very long lines are read. The 16-+and 32-bit buffers (pbuffer16, pbuffer32) are obtained only if needed. */++buffer = (uint8_t *)malloc(pbuffer8_size);+pbuffer8 = (uint8_t *)malloc(pbuffer8_size);++/* The following _setmode() stuff is some Windows magic that tells its runtime+library to translate CRLF into a single LF character. At least, that's what+I've been told: never having used Windows I take this all on trust. Originally+it set 0x8000, but then I was advised that _O_BINARY was better. */++#if defined(_WIN32) || defined(WIN32)+_setmode( _fileno( stdout ), _O_BINARY );+#endif++/* Initialization that does not depend on the running mode. */++locale_name[0] = 0;++memset(&def_patctl, 0, sizeof(patctl));+def_patctl.convert_type = CONVERT_UNSET;++memset(&def_datctl, 0, sizeof(datctl));+def_datctl.oveccount = DEFAULT_OVECCOUNT;+def_datctl.copy_numbers[0] = -1;+def_datctl.get_numbers[0] = -1;+def_datctl.startend[0] = def_datctl.startend[1] = CFORE_UNSET;+def_datctl.cerror[0] = def_datctl.cerror[1] = CFORE_UNSET;+def_datctl.cfail[0] = def_datctl.cfail[1] = CFORE_UNSET;++/* Scan command line options. */++while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)+ {+ char *endptr;+ char *arg = argv[op];+ unsigned long uli;++ /* List modifiers and exit. */++ if (strcmp(arg, "-LM") == 0)+ {+ display_modifiers();+ goto EXIT;+ }++ /* Display and/or set return code for configuration options. */++ if (strcmp(arg, "-C") == 0)+ {+ yield = c_option(argv[op + 1]);+ goto EXIT;+ }++ /* Select operating mode. Ensure that pcre2_config() is called in 16-bit+ and 32-bit modes because that won't happen naturally when 8-bit is also+ configured. Also call some other functions that are not otherwise used. This+ means that a coverage report won't claim there are uncalled functions. */++ if (strcmp(arg, "-8") == 0)+ {+#ifdef SUPPORT_PCRE2_8+ test_mode = PCRE8_MODE;+ (void)pcre2_set_bsr_8(pat_context8, 999);+ (void)pcre2_set_newline_8(pat_context8, 999);+#else+ fprintf(stderr,+ "** This version of PCRE2 was built without 8-bit support\n");+ exit(1);+#endif+ }++ else if (strcmp(arg, "-16") == 0)+ {+#ifdef SUPPORT_PCRE2_16+ test_mode = PCRE16_MODE;+ (void)pcre2_config_16(PCRE2_CONFIG_VERSION, NULL);+ (void)pcre2_set_bsr_16(pat_context16, 999);+ (void)pcre2_set_newline_16(pat_context16, 999);+#else+ fprintf(stderr,+ "** This version of PCRE2 was built without 16-bit support\n");+ exit(1);+#endif+ }++ else if (strcmp(arg, "-32") == 0)+ {+#ifdef SUPPORT_PCRE2_32+ test_mode = PCRE32_MODE;+ (void)pcre2_config_32(PCRE2_CONFIG_VERSION, NULL);+ (void)pcre2_set_bsr_32(pat_context32, 999);+ (void)pcre2_set_newline_32(pat_context32, 999);+#else+ fprintf(stderr,+ "** This version of PCRE2 was built without 32-bit support\n");+ exit(1);+#endif+ }++ /* Set quiet (no version verification) */++ else if (strcmp(arg, "-q") == 0) quiet = TRUE;++ /* Set system stack size */++ else if (strcmp(arg, "-S") == 0 && argc > 2 &&+ ((uli = strtoul(argv[op+1], &endptr, 10)), *endptr == 0))+ {+#if defined(_WIN32) || defined(WIN32) || defined(__minix) || defined(NATIVE_ZOS) || defined(__VMS)+ fprintf(stderr, "pcre2test: -S is not supported on this OS\n");+ exit(1);+#else+ int rc;+ uint32_t stack_size;+ struct rlimit rlim;+ if (U32OVERFLOW(uli))+ {+ fprintf(stderr, "** Argument for -S is too big\n");+ exit(1);+ }+ stack_size = (uint32_t)uli;+ getrlimit(RLIMIT_STACK, &rlim);+ rlim.rlim_cur = stack_size * 1024 * 1024;+ if (rlim.rlim_cur > rlim.rlim_max)+ {+ fprintf(stderr,+ "pcre2test: requested stack size %luMiB is greater than hard limit "+ "%luMiB\n", (unsigned long int)stack_size,+ (unsigned long int)(rlim.rlim_max));+ exit(1);+ }+ rc = setrlimit(RLIMIT_STACK, &rlim);+ if (rc != 0)+ {+ fprintf(stderr, "pcre2test: setting stack size %luMiB failed: %s\n",+ (unsigned long int)stack_size, strerror(errno));+ exit(1);+ }+ op++;+ argc--;+#endif+ }++ /* Set some common pattern and subject controls */++ else if (strcmp(arg, "-AC") == 0)+ {+ def_patctl.options |= PCRE2_AUTO_CALLOUT;+ def_datctl.control2 |= CTL2_CALLOUT_EXTRA;+ }+ else if (strcmp(arg, "-ac") == 0) def_patctl.options |= PCRE2_AUTO_CALLOUT;+ else if (strcmp(arg, "-b") == 0) def_patctl.control |= CTL_FULLBINCODE;+ else if (strcmp(arg, "-d") == 0) def_patctl.control |= CTL_DEBUG;+ else if (strcmp(arg, "-dfa") == 0) def_datctl.control |= CTL_DFA;+ else if (strcmp(arg, "-i") == 0) def_patctl.control |= CTL_INFO;+ else if (strcmp(arg, "-jit") == 0 || strcmp(arg, "-jitverify") == 0 ||+ strcmp(arg, "-jitfast") == 0)+ {+ if (arg[4] == 'v') def_patctl.control |= CTL_JITVERIFY;+ else if (arg[4] == 'f') def_patctl.control |= CTL_JITFAST;+ def_patctl.jit = JIT_DEFAULT; /* full & partial */+#ifndef SUPPORT_JIT+ fprintf(stderr, "** Warning: JIT support is not available: "+ "-jit[fast|verify] calls functions that do nothing.\n");+#endif+ }++ /* Set timing parameters */++ else if (strcmp(arg, "-t") == 0 || strcmp(arg, "-tm") == 0 ||+ strcmp(arg, "-T") == 0 || strcmp(arg, "-TM") == 0)+ {+ int both = arg[2] == 0;+ showtotaltimes = arg[1] == 'T';+ if (argc > 2 && (uli = strtoul(argv[op+1], &endptr, 10), *endptr == 0))+ {+ if (uli == 0)+ {+ fprintf(stderr, "** Argument for %s must not be zero\n", arg);+ exit(1);+ }+ if (U32OVERFLOW(uli))+ {+ fprintf(stderr, "** Argument for %s is too big\n", arg);+ exit(1);+ }+ timeitm = (int)uli;+ op++;+ argc--;+ }+ else timeitm = LOOPREPEAT;+ if (both) timeit = timeitm;+ }++ /* Give help */++ else if (strcmp(arg, "-help") == 0 ||+ strcmp(arg, "--help") == 0)+ {+ usage();+ goto EXIT;+ }++ /* Show version */++ else if (strcmp(arg, "-version") == 0 ||+ strcmp(arg, "--version") == 0)+ {+ print_version(stdout);+ goto EXIT;+ }++ /* The following options save their data for processing once we know what+ the running mode is. */++ else if (strcmp(arg, "-error") == 0)+ {+ arg_error = argv[op+1];+ goto CHECK_VALUE_EXISTS;+ }++ else if (strcmp(arg, "-subject") == 0)+ {+ arg_subject = argv[op+1];+ goto CHECK_VALUE_EXISTS;+ }++ else if (strcmp(arg, "-pattern") == 0)+ {+ arg_pattern = argv[op+1];+ CHECK_VALUE_EXISTS:+ if (argc <= 2)+ {+ fprintf(stderr, "** Missing value for %s\n", arg);+ yield = 1;+ goto EXIT;+ }+ op++;+ argc--;+ }++ /* Unrecognized option */++ else+ {+ fprintf(stderr, "** Unknown or malformed option '%s'\n", arg);+ usage();+ yield = 1;+ goto EXIT;+ }+ op++;+ argc--;+ }++/* If -error was present, get the error numbers, show the messages, and exit.+We wait to do this until we know which mode we are in. */++if (arg_error != NULL)+ {+ int len;+ int errcode;+ char *endptr;++/* Ensure the relevant non-8-bit buffer is available. Ensure that it is at+least 128 code units, because it is used for retrieving error messages. */++#ifdef SUPPORT_PCRE2_16+ if (test_mode == PCRE16_MODE)+ {+ pbuffer16_size = 256;+ pbuffer16 = (uint16_t *)malloc(pbuffer16_size);+ if (pbuffer16 == NULL)+ {+ fprintf(stderr, "pcre2test: malloc(%" SIZ_FORM ") failed for pbuffer16\n",+ SIZ_CAST pbuffer16_size);+ yield = 1;+ goto EXIT;+ }+ }+#endif++#ifdef SUPPORT_PCRE2_32+ if (test_mode == PCRE32_MODE)+ {+ pbuffer32_size = 512;+ pbuffer32 = (uint32_t *)malloc(pbuffer32_size);+ if (pbuffer32 == NULL)+ {+ fprintf(stderr, "pcre2test: malloc(%" SIZ_FORM ") failed for pbuffer32\n",+ SIZ_CAST pbuffer32_size);+ yield = 1;+ goto EXIT;+ }+ }+#endif++ /* Loop along a list of error numbers. */++ for (;;)+ {+ errcode = strtol(arg_error, &endptr, 10);+ if (*endptr != 0 && *endptr != CHAR_COMMA)+ {+ fprintf(stderr, "** '%s' is not a valid error number list\n", arg_error);+ yield = 1;+ goto EXIT;+ }+ printf("Error %d: ", errcode);+ PCRE2_GET_ERROR_MESSAGE(len, errcode, pbuffer);+ if (len < 0)+ {+ switch (len)+ {+ case PCRE2_ERROR_BADDATA:+ printf("PCRE2_ERROR_BADDATA (unknown error number)");+ break;++ case PCRE2_ERROR_NOMEMORY:+ printf("PCRE2_ERROR_NOMEMORY (buffer too small)");+ break;++ default:+ printf("Unexpected return (%d) from pcre2_get_error_message()", len);+ break;+ }+ }+ else+ {+ PCHARSV(CASTVAR(void *, pbuffer), 0, len, FALSE, stdout);+ }+ printf("\n");+ if (*endptr == 0) goto EXIT;+ arg_error = endptr + 1;+ }+ /* Control never reaches here */+ } /* End of -error handling */++/* Initialize things that cannot be done until we know which test mode we are+running in. Exercise the general context copying and match data size functions,+which are not otherwise used. */++code_unit_size = test_mode/8;+max_oveccount = DEFAULT_OVECCOUNT;++/* Use macros to save a lot of duplication. */++#define CREATECONTEXTS \+ G(general_context,BITS) = G(pcre2_general_context_create_,BITS)(&my_malloc, &my_free, NULL); \+ G(general_context_copy,BITS) = G(pcre2_general_context_copy_,BITS)(G(general_context,BITS)); \+ G(default_pat_context,BITS) = G(pcre2_compile_context_create_,BITS)(G(general_context,BITS)); \+ G(pat_context,BITS) = G(pcre2_compile_context_copy_,BITS)(G(default_pat_context,BITS)); \+ G(default_dat_context,BITS) = G(pcre2_match_context_create_,BITS)(G(general_context,BITS)); \+ G(dat_context,BITS) = G(pcre2_match_context_copy_,BITS)(G(default_dat_context,BITS)); \+ G(default_con_context,BITS) = G(pcre2_convert_context_create_,BITS)(G(general_context,BITS)); \+ G(con_context,BITS) = G(pcre2_convert_context_copy_,BITS)(G(default_con_context,BITS)); \+ G(match_data,BITS) = G(pcre2_match_data_create_,BITS)(max_oveccount, G(general_context,BITS))++#define CONTEXTTESTS \+ (void)G(pcre2_set_compile_extra_options_,BITS)(G(pat_context,BITS), 0); \+ (void)G(pcre2_set_max_pattern_length_,BITS)(G(pat_context,BITS), 0); \+ (void)G(pcre2_set_offset_limit_,BITS)(G(dat_context,BITS), 0); \+ (void)G(pcre2_set_recursion_memory_management_,BITS)(G(dat_context,BITS), my_malloc, my_free, NULL); \+ (void)G(pcre2_get_match_data_size_,BITS)(G(match_data,BITS))+++/* Call the appropriate functions for the current mode, and exercise some+functions that are not otherwise called. */++#ifdef SUPPORT_PCRE2_8+#undef BITS+#define BITS 8+if (test_mode == PCRE8_MODE)+ {+ CREATECONTEXTS;+ CONTEXTTESTS;+ }+#endif++#ifdef SUPPORT_PCRE2_16+#undef BITS+#define BITS 16+if (test_mode == PCRE16_MODE)+ {+ CREATECONTEXTS;+ CONTEXTTESTS;+ }+#endif++#ifdef SUPPORT_PCRE2_32+#undef BITS+#define BITS 32+if (test_mode == PCRE32_MODE)+ {+ CREATECONTEXTS;+ CONTEXTTESTS;+ }+#endif++/* Set a default parentheses nest limit that is large enough to run the+standard tests (this also exercises the function). */++PCRE2_SET_PARENS_NEST_LIMIT(default_pat_context, PARENS_NEST_DEFAULT);++/* Handle command line modifier settings, sending any error messages to+stderr. We need to know the mode before modifying the context, and it is tidier+to do them all in the same way. */++outfile = stderr;+if ((arg_pattern != NULL &&+ !decode_modifiers((uint8_t *)arg_pattern, CTX_DEFPAT, &def_patctl, NULL)) ||+ (arg_subject != NULL &&+ !decode_modifiers((uint8_t *)arg_subject, CTX_DEFDAT, NULL, &def_datctl)))+ {+ yield = 1;+ goto EXIT;+ }++/* Sort out the input and output files, defaulting to stdin/stdout. */++infile = stdin;+outfile = stdout;++if (argc > 1 && strcmp(argv[op], "-") != 0)+ {+ infile = fopen(argv[op], INPUT_MODE);+ if (infile == NULL)+ {+ printf("** Failed to open '%s': %s\n", argv[op], strerror(errno));+ yield = 1;+ goto EXIT;+ }+ }++#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+if (INTERACTIVE(infile)) using_history();+#endif++if (argc > 2)+ {+ outfile = fopen(argv[op+1], OUTPUT_MODE);+ if (outfile == NULL)+ {+ printf("** Failed to open '%s': %s\n", argv[op+1], strerror(errno));+ yield = 1;+ goto EXIT;+ }+ }++/* Output a heading line unless quiet, then process input lines. */++if (!quiet) print_version(outfile);++SET(compiled_code, NULL);++#ifdef SUPPORT_PCRE2_8+preg.re_pcre2_code = NULL;+preg.re_match_data = NULL;+#endif++while (notdone)+ {+ uint8_t *p;+ int rc = PR_OK;+ BOOL expectdata = TEST(compiled_code, !=, NULL);+#ifdef SUPPORT_PCRE2_8+ expectdata |= preg.re_pcre2_code != NULL;+#endif++ if (extend_inputline(infile, buffer, expectdata? "data> " : " re> ") == NULL)+ break;+ if (!INTERACTIVE(infile)) fprintf(outfile, "%s", (char *)buffer);+ fflush(outfile);+ p = buffer;++ /* If we have a pattern set up for testing, or we are skipping after a+ compile failure, a blank line terminates this test. */++ if (expectdata || skipping)+ {+ while (isspace(*p)) p++;+ if (*p == 0)+ {+#ifdef SUPPORT_PCRE2_8+ if (preg.re_pcre2_code != NULL)+ {+ regfree(&preg);+ preg.re_pcre2_code = NULL;+ preg.re_match_data = NULL;+ }+#endif /* SUPPORT_PCRE2_8 */+ if (TEST(compiled_code, !=, NULL))+ {+ SUB1(pcre2_code_free, compiled_code);+ SET(compiled_code, NULL);+ }+ skipping = FALSE;+ setlocale(LC_CTYPE, "C");+ }++ /* Otherwise, if we are not skipping, and the line is not a data comment+ line starting with "\=", process a data line. */++ else if (!skipping && !(p[0] == '\\' && p[1] == '=' && isspace(p[2])))+ {+ rc = process_data();+ }+ }++ /* We do not have a pattern set up for testing. Lines starting with # are+ either comments or special commands. Blank lines are ignored. Otherwise, the+ line must start with a valid delimiter. It is then processed as a pattern+ line. A copy of the pattern is left in pbuffer8 for use by callouts. Under+ valgrind, make the unused part of the buffer undefined, to catch overruns. */++ else if (*p == '#')+ {+ if (isspace(p[1]) || p[1] == '!' || p[1] == 0) continue;+ rc = process_command();+ }++ else if (strchr("/!\"'`%&-=_:;,@~", *p) != NULL)+ {+ rc = process_pattern();+ dfa_matched = 0;+ }++ else+ {+ while (isspace(*p)) p++;+ if (*p != 0)+ {+ fprintf(outfile, "** Invalid pattern delimiter '%c' (x%x).\n", *buffer,+ *buffer);+ rc = PR_SKIP;+ }+ }++ if (rc == PR_SKIP && !INTERACTIVE(infile)) skipping = TRUE;+ else if (rc == PR_ABEND)+ {+ fprintf(outfile, "** pcre2test run abandoned\n");+ yield = 1;+ goto EXIT;+ }+ }++/* Finish off a normal run. */++if (INTERACTIVE(infile)) fprintf(outfile, "\n");++if (showtotaltimes)+ {+ const char *pad = "";+ fprintf(outfile, "--------------------------------------\n");+ if (timeit > 0)+ {+ fprintf(outfile, "Total compile time %.4f milliseconds\n",+ (((double)total_compile_time * 1000.0) / (double)timeit) /+ (double)CLOCKS_PER_SEC);+ if (total_jit_compile_time > 0)+ fprintf(outfile, "Total JIT compile %.4f milliseconds\n",+ (((double)total_jit_compile_time * 1000.0) / (double)timeit) /+ (double)CLOCKS_PER_SEC);+ pad = " ";+ }+ fprintf(outfile, "Total match time %s%.4f milliseconds\n", pad,+ (((double)total_match_time * 1000.0) / (double)timeitm) /+ (double)CLOCKS_PER_SEC);+ }+++EXIT:++#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+if (infile != NULL && INTERACTIVE(infile)) clear_history();+#endif++if (infile != NULL && infile != stdin) fclose(infile);+if (outfile != NULL && outfile != stdout) fclose(outfile);++free(buffer);+free(dbuffer);+free(pbuffer8);+free(dfa_workspace);+free((void *)locale_tables);+free(tables3);+PCRE2_MATCH_DATA_FREE(match_data);+SUB1(pcre2_code_free, compiled_code);++while(patstacknext-- > 0)+ {+ SET(compiled_code, patstack[patstacknext]);+ SUB1(pcre2_code_free, compiled_code);+ }++PCRE2_JIT_FREE_UNUSED_MEMORY(general_context);+if (jit_stack != NULL)+ {+ PCRE2_JIT_STACK_FREE(jit_stack);+ }++#define FREECONTEXTS \+ G(pcre2_general_context_free_,BITS)(G(general_context,BITS)); \+ G(pcre2_general_context_free_,BITS)(G(general_context_copy,BITS)); \+ G(pcre2_compile_context_free_,BITS)(G(pat_context,BITS)); \+ G(pcre2_compile_context_free_,BITS)(G(default_pat_context,BITS)); \+ G(pcre2_match_context_free_,BITS)(G(dat_context,BITS)); \+ G(pcre2_match_context_free_,BITS)(G(default_dat_context,BITS)); \+ G(pcre2_convert_context_free_,BITS)(G(default_con_context,BITS)); \+ G(pcre2_convert_context_free_,BITS)(G(con_context,BITS));++#ifdef SUPPORT_PCRE2_8+#undef BITS+#define BITS 8+if (preg.re_pcre2_code != NULL) regfree(&preg);+FREECONTEXTS;+#endif++#ifdef SUPPORT_PCRE2_16+#undef BITS+#define BITS 16+free(pbuffer16);+FREECONTEXTS;+#endif++#ifdef SUPPORT_PCRE2_32+#undef BITS+#define BITS 32+free(pbuffer32);+FREECONTEXTS;+#endif++#if defined(__VMS)+ yield = SS$_NORMAL; /* Return values via DCL symbols */+#endif++return yield;+}++/* End of pcre2test.c */
+ src/c/pcre2/src/sljit/sljitConfig.h view
@@ -0,0 +1,172 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++#ifndef SLJIT_CONFIG_H_+#define SLJIT_CONFIG_H_++#ifdef __cplusplus+extern "C" {+#endif++/*+ This file contains the basic configuration options for the SLJIT compiler+ and their default values. These options can be overridden in the+ sljitConfigPre.h header file when SLJIT_HAVE_CONFIG_PRE is set to a+ non-zero value.+*/++/* --------------------------------------------------------------------- */+/* Architecture */+/* --------------------------------------------------------------------- */++/* Architecture selection. */+/* #define SLJIT_CONFIG_X86_32 1 */+/* #define SLJIT_CONFIG_X86_64 1 */+/* #define SLJIT_CONFIG_ARM_V5 1 */+/* #define SLJIT_CONFIG_ARM_V7 1 */+/* #define SLJIT_CONFIG_ARM_THUMB2 1 */+/* #define SLJIT_CONFIG_ARM_64 1 */+/* #define SLJIT_CONFIG_PPC_32 1 */+/* #define SLJIT_CONFIG_PPC_64 1 */+/* #define SLJIT_CONFIG_MIPS_32 1 */+/* #define SLJIT_CONFIG_MIPS_64 1 */+/* #define SLJIT_CONFIG_SPARC_32 1 */+/* #define SLJIT_CONFIG_TILEGX 1 */++/* #define SLJIT_CONFIG_AUTO 1 */+/* #define SLJIT_CONFIG_UNSUPPORTED 1 */++/* --------------------------------------------------------------------- */+/* Utilities */+/* --------------------------------------------------------------------- */++/* Implements a stack like data structure (by using mmap / VirtualAlloc */+/* or a custom allocator). */+#ifndef SLJIT_UTIL_STACK+/* Enabled by default */+#define SLJIT_UTIL_STACK 1+#endif++/* Uses user provided allocator to allocate the stack (see SLJIT_UTIL_STACK) */+#ifndef SLJIT_UTIL_SIMPLE_STACK_ALLOCATION+/* Disabled by default */+#define SLJIT_UTIL_SIMPLE_STACK_ALLOCATION 0+#endif++/* Single threaded application. Does not require any locks. */+#ifndef SLJIT_SINGLE_THREADED+/* Disabled by default. */+#define SLJIT_SINGLE_THREADED 0+#endif++/* --------------------------------------------------------------------- */+/* Configuration */+/* --------------------------------------------------------------------- */++/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should+ define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMCPY, and NULL. */+#ifndef SLJIT_STD_MACROS_DEFINED+/* Disabled by default. */+#define SLJIT_STD_MACROS_DEFINED 0+#endif++/* Executable code allocation:+ If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should+ define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_EXEC_OFFSET. */+#ifndef SLJIT_EXECUTABLE_ALLOCATOR+/* Enabled by default. */+#define SLJIT_EXECUTABLE_ALLOCATOR 1++/* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses+ an allocator which does not set writable and executable+ permission flags at the same time.+ Instead, it creates a shared memory segment (usually backed by a file)+ and maps it twice, with different permissions, depending on the use+ case.+ The trade-off is increased use of virtual memory, incompatibility with+ fork(), and some possible additional security risks by the use of+ publicly accessible files for the generated code. */+#ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR+/* Disabled by default. */+#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0+#endif++/* When SLJIT_WX_EXECUTABLE_ALLOCATOR is enabled SLJIT uses an+ allocator which does not set writable and executable permission+ flags at the same time.+ Instead, it creates a new independent map on each invocation and+ switches permissions at the underlying pages as needed.+ The trade-off is increased memory use and degraded performance. */+#ifndef SLJIT_WX_EXECUTABLE_ALLOCATOR+/* Disabled by default. */+#define SLJIT_WX_EXECUTABLE_ALLOCATOR 0+#endif++#endif /* !SLJIT_EXECUTABLE_ALLOCATOR */++/* Force cdecl calling convention even if a better calling+ convention (e.g. fastcall) is supported by the C compiler.+ If this option is disabled (this is the default), functions+ called from JIT should be defined with SLJIT_FUNC attribute.+ Standard C functions can still be called by using the+ SLJIT_CALL_CDECL jump type. */+#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION+/* Disabled by default */+#define SLJIT_USE_CDECL_CALLING_CONVENTION 0+#endif++/* Return with error when an invalid argument is passed. */+#ifndef SLJIT_ARGUMENT_CHECKS+/* Disabled by default */+#define SLJIT_ARGUMENT_CHECKS 0+#endif++/* Debug checks (assertions, etc.). */+#ifndef SLJIT_DEBUG+/* Enabled by default */+#define SLJIT_DEBUG 1+#endif++/* Verbose operations. */+#ifndef SLJIT_VERBOSE+/* Enabled by default */+#define SLJIT_VERBOSE 1+#endif++/*+ SLJIT_IS_FPU_AVAILABLE+ The availability of the FPU can be controlled by SLJIT_IS_FPU_AVAILABLE.+ zero value - FPU is NOT present.+ nonzero value - FPU is present.+*/++/* For further configurations, see the beginning of sljitConfigInternal.h */++#ifdef __cplusplus+} /* extern "C" */+#endif++#endif /* SLJIT_CONFIG_H_ */
+ src/c/pcre2/src/sljit/sljitConfigInternal.h view
@@ -0,0 +1,800 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++#ifndef SLJIT_CONFIG_INTERNAL_H_+#define SLJIT_CONFIG_INTERNAL_H_++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)))+#include <stdio.h>+#endif++#if (defined SLJIT_DEBUG && SLJIT_DEBUG \+ && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) || !defined(SLJIT_HALT_PROCESS)))+#include <stdlib.h>+#endif++#ifdef __cplusplus+extern "C" {+#endif++/*+ SLJIT defines the following architecture dependent types and macros:++ Types:+ sljit_s8, sljit_u8 : signed and unsigned 8 bit integer type+ sljit_s16, sljit_u16 : signed and unsigned 16 bit integer type+ sljit_s32, sljit_u32 : signed and unsigned 32 bit integer type+ sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer+ sljit_p : unsgined pointer value (usually the same as sljit_uw, but+ some 64 bit ABIs may use 32 bit pointers)+ sljit_f32 : 32 bit single precision floating point value+ sljit_f64 : 64 bit double precision floating point value++ Macros for feature detection (boolean):+ SLJIT_32BIT_ARCHITECTURE : 32 bit architecture+ SLJIT_64BIT_ARCHITECTURE : 64 bit architecture+ SLJIT_LITTLE_ENDIAN : little endian architecture+ SLJIT_BIG_ENDIAN : big endian architecture+ SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)+ SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information++ Constants:+ SLJIT_NUMBER_OF_REGISTERS : number of available registers+ SLJIT_NUMBER_OF_SCRATCH_REGISTERS : number of available scratch registers+ SLJIT_NUMBER_OF_SAVED_REGISTERS : number of available saved registers+ SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers+ SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available floating point scratch registers+ SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available floating point saved registers+ SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index+ SLJIT_F32_SHIFT : the shift required to apply when accessing+ a single precision floating point array by index+ SLJIT_F64_SHIFT : the shift required to apply when accessing+ a double precision floating point array by index+ SLJIT_PREF_SHIFT_REG : x86 systems prefers ecx for shifting by register+ the scratch register index of ecx is stored in this variable+ SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET)+ SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address++ Other macros:+ SLJIT_FUNC : calling convention attribute for both calling JIT from C and C calling back from JIT+ SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (platform independent helper)+*/++/*****************/+/* Sanity check. */+/*****************/++#if !((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \+ || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \+ || (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \+ || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \+ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \+ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \+ || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \+ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \+ || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \+ || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \+ || (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \+ || (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \+ || (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED))+#error "An architecture must be selected"+#endif++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \+ + (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \+ + (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \+ + (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \+ + (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \+ + (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \+ + (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \+ + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \+ + (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \+ + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \+ + (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \+ + (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \+ + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \+ + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2+#error "Multiple architectures are selected"+#endif++/********************************************************/+/* Automatic CPU detection (requires compiler support). */+/********************************************************/++#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)++#ifndef _WIN32++#if defined(__i386__) || defined(__i386)+#define SLJIT_CONFIG_X86_32 1+#elif defined(__x86_64__)+#define SLJIT_CONFIG_X86_64 1+#elif defined(__arm__) || defined(__ARM__)+#ifdef __thumb2__+#define SLJIT_CONFIG_ARM_THUMB2 1+#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__)+#define SLJIT_CONFIG_ARM_V7 1+#else+#define SLJIT_CONFIG_ARM_V5 1+#endif+#elif defined (__aarch64__)+#define SLJIT_CONFIG_ARM_64 1+#elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_PPC64) || (defined(_POWER) && defined(__64BIT__))+#define SLJIT_CONFIG_PPC_64 1+#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)+#define SLJIT_CONFIG_PPC_32 1+#elif defined(__mips__) && !defined(_LP64)+#define SLJIT_CONFIG_MIPS_32 1+#elif defined(__mips64)+#define SLJIT_CONFIG_MIPS_64 1+#elif defined(__sparc__) || defined(__sparc)+#define SLJIT_CONFIG_SPARC_32 1+#elif defined(__tilegx__)+#define SLJIT_CONFIG_TILEGX 1+#else+/* Unsupported architecture */+#define SLJIT_CONFIG_UNSUPPORTED 1+#endif++#else /* _WIN32 */++#if defined(_M_X64) || defined(__x86_64__)+#define SLJIT_CONFIG_X86_64 1+#elif (defined(_M_ARM) && _M_ARM >= 7 && defined(_M_ARMT)) || defined(__thumb2__)+#define SLJIT_CONFIG_ARM_THUMB2 1+#elif (defined(_M_ARM) && _M_ARM >= 7)+#define SLJIT_CONFIG_ARM_V7 1+#elif defined(_ARM_)+#define SLJIT_CONFIG_ARM_V5 1+#elif defined(_M_ARM64) || defined(__aarch64__)+#define SLJIT_CONFIG_ARM_64 1+#else+#define SLJIT_CONFIG_X86_32 1+#endif++#endif /* !_WIN32 */+#endif /* SLJIT_CONFIG_AUTO */++#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)+#undef SLJIT_EXECUTABLE_ALLOCATOR+#endif++/******************************/+/* CPU family type detection. */+/******************************/++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \+ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+#define SLJIT_CONFIG_ARM_32 1+#endif++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+#define SLJIT_CONFIG_X86 1+#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+#define SLJIT_CONFIG_ARM 1+#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define SLJIT_CONFIG_PPC 1+#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+#define SLJIT_CONFIG_MIPS 1+#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) || (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)+#define SLJIT_CONFIG_SPARC 1+#endif++/***********************************************************/+/* Intel Control-flow Enforcement Technology (CET) spport. */+/***********************************************************/++#ifdef SLJIT_CONFIG_X86++#if defined(__CET__) && !(defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)+#define SLJIT_CONFIG_X86_CET 1+#endif++#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined(__GNUC__)+#include <x86intrin.h>+#endif++#endif /* SLJIT_CONFIG_X86 */++/**********************************/+/* External function definitions. */+/**********************************/++/* General macros:+ Note: SLJIT is designed to be independent from them as possible.++ In release mode (SLJIT_DEBUG is not defined) only the following+ external functions are needed:+*/++#ifndef SLJIT_MALLOC+#define SLJIT_MALLOC(size, allocator_data) malloc(size)+#endif++#ifndef SLJIT_FREE+#define SLJIT_FREE(ptr, allocator_data) free(ptr)+#endif++#ifndef SLJIT_MEMCPY+#define SLJIT_MEMCPY(dest, src, len) memcpy(dest, src, len)+#endif++#ifndef SLJIT_MEMMOVE+#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)+#endif++#ifndef SLJIT_ZEROMEM+#define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len)+#endif++/***************************/+/* Compiler helper macros. */+/***************************/++#if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY)++#if defined(__GNUC__) && (__GNUC__ >= 3)+#define SLJIT_LIKELY(x) __builtin_expect((x), 1)+#define SLJIT_UNLIKELY(x) __builtin_expect((x), 0)+#else+#define SLJIT_LIKELY(x) (x)+#define SLJIT_UNLIKELY(x) (x)+#endif++#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */++#ifndef SLJIT_INLINE+/* Inline functions. Some old compilers do not support them. */+#if defined(__SUNPRO_C) && __SUNPRO_C <= 0x510+#define SLJIT_INLINE+#else+#define SLJIT_INLINE __inline+#endif+#endif /* !SLJIT_INLINE */++#ifndef SLJIT_NOINLINE+/* Not inline functions. */+#if defined(__GNUC__)+#define SLJIT_NOINLINE __attribute__ ((noinline))+#else+#define SLJIT_NOINLINE+#endif+#endif /* !SLJIT_INLINE */++#ifndef SLJIT_UNUSED_ARG+/* Unused arguments. */+#define SLJIT_UNUSED_ARG(arg) (void)arg+#endif++/*********************************/+/* Type of public API functions. */+/*********************************/++#ifndef SLJIT_API_FUNC_ATTRIBUTE +#if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC)+/* Static ABI functions. For all-in-one programs. */++#if defined(__GNUC__)+/* Disable unused warnings in gcc. */+#define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused))+#else+#define SLJIT_API_FUNC_ATTRIBUTE static+#endif++#else+#define SLJIT_API_FUNC_ATTRIBUTE+#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */+#endif /* defined SLJIT_API_FUNC_ATTRIBUTE */++/****************************/+/* Instruction cache flush. */+/****************************/++#if (!defined SLJIT_CACHE_FLUSH && defined __has_builtin)+#if __has_builtin(__builtin___clear_cache)++#define SLJIT_CACHE_FLUSH(from, to) \+ __builtin___clear_cache((char*)(from), (char*)(to))++#endif /* __has_builtin(__builtin___clear_cache) */+#endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */++#ifndef SLJIT_CACHE_FLUSH++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)++/* Not required to implement on archs with unified caches. */+#define SLJIT_CACHE_FLUSH(from, to)++#elif defined __APPLE__++/* Supported by all macs since Mac OS 10.5.+ However, it does not work on non-jailbroken iOS devices,+ although the compilation is successful. */++#define SLJIT_CACHE_FLUSH(from, to) \+ sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from))++#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)++/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */+#define SLJIT_CACHE_FLUSH(from, to) \+ ppc_cache_flush((from), (to))+#define SLJIT_CACHE_FLUSH_OWN_IMPL 1++#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))++#define SLJIT_CACHE_FLUSH(from, to) \+ __builtin___clear_cache((char*)(from), (char*)(to))++#elif defined __ANDROID__++/* Android lacks __clear_cache; instead, cacheflush should be used. */++#define SLJIT_CACHE_FLUSH(from, to) \+ cacheflush((long)(from), (long)(to), 0)++#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)++/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */+#define SLJIT_CACHE_FLUSH(from, to) \+ sparc_cache_flush((from), (to))+#define SLJIT_CACHE_FLUSH_OWN_IMPL 1++#elif defined _WIN32++#define SLJIT_CACHE_FLUSH(from, to) \+ FlushInstructionCache(GetCurrentProcess(), (char*)(from), (char*)(to) - (char*)(from))++#else++/* Calls __ARM_NR_cacheflush on ARM-Linux. */+#define SLJIT_CACHE_FLUSH(from, to) \+ __clear_cache((char*)(from), (char*)(to))++#endif++#endif /* !SLJIT_CACHE_FLUSH */++/******************************************************/+/* Integer and floating point type definitions. */+/******************************************************/++/* 8 bit byte type. */+typedef unsigned char sljit_u8;+typedef signed char sljit_s8;++/* 16 bit half-word type. */+typedef unsigned short int sljit_u16;+typedef signed short int sljit_s16;++/* 32 bit integer type. */+typedef unsigned int sljit_u32;+typedef signed int sljit_s32;++/* Machine word type. Enough for storing a pointer.+ 32 bit for 32 bit machines.+ 64 bit for 64 bit machines. */+#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)+/* Just to have something. */+#define SLJIT_WORD_SHIFT 0+typedef unsigned long int sljit_uw;+typedef long int sljit_sw;+#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \+ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \+ && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \+ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \+ && !(defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)+#define SLJIT_32BIT_ARCHITECTURE 1+#define SLJIT_WORD_SHIFT 2+typedef unsigned int sljit_uw;+typedef int sljit_sw;+#else+#define SLJIT_64BIT_ARCHITECTURE 1+#define SLJIT_WORD_SHIFT 3+#ifdef _WIN32+#ifdef __GNUC__+/* These types do not require windows.h */+typedef unsigned long long sljit_uw;+typedef long long sljit_sw;+#else+typedef unsigned __int64 sljit_uw;+typedef __int64 sljit_sw;+#endif+#else /* !_WIN32 */+typedef unsigned long int sljit_uw;+typedef long int sljit_sw;+#endif /* _WIN32 */+#endif++typedef sljit_uw sljit_p;++/* Floating point types. */+typedef float sljit_f32;+typedef double sljit_f64;++/* Shift for pointer sized data. */+#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT++/* Shift for double precision sized data. */+#define SLJIT_F32_SHIFT 2+#define SLJIT_F64_SHIFT 3++#ifndef SLJIT_W++/* Defining long constants. */+#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)+#define SLJIT_W(w) (w##l)+#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+#ifdef _WIN64+#define SLJIT_W(w) (w##ll)+#else /* !windows */+#define SLJIT_W(w) (w##l)+#endif /* windows */+#else /* 32 bit */+#define SLJIT_W(w) (w)+#endif /* unknown */++#endif /* !SLJIT_W */++/*************************/+/* Endianness detection. */+/*************************/++#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)++/* These macros are mostly useful for the applications. */+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \+ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)++#ifdef __LITTLE_ENDIAN__+#define SLJIT_LITTLE_ENDIAN 1+#else+#define SLJIT_BIG_ENDIAN 1+#endif++#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \+ || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)++#ifdef __MIPSEL__+#define SLJIT_LITTLE_ENDIAN 1+#else+#define SLJIT_BIG_ENDIAN 1+#endif++#ifndef SLJIT_MIPS_REV++/* Auto detecting mips revision. */+#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6)+#define SLJIT_MIPS_REV 6+#elif (defined __mips_isa_rev && __mips_isa_rev >= 1) \+ || (defined __clang__ && defined _MIPS_ARCH_OCTEON) \+ || (defined __clang__ && defined _MIPS_ARCH_P5600)+/* clang either forgets to define (clang-7) __mips_isa_rev at all+ * or sets it to zero (clang-8,-9) for -march=octeon (MIPS64 R2+)+ * and -march=p5600 (MIPS32 R5).+ * It also sets the __mips macro to 64 or 32 for -mipsN when N <= 5+ * (should be set to N exactly) so we cannot rely on this too.+ */+#define SLJIT_MIPS_REV 1+#endif++#endif /* !SLJIT_MIPS_REV */++#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)++#define SLJIT_BIG_ENDIAN 1++#else+#define SLJIT_LITTLE_ENDIAN 1+#endif++#endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */++/* Sanity check. */+#if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#error "Exactly one endianness must be selected"+#endif++#if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#error "Exactly one endianness must be selected"+#endif++#ifndef SLJIT_UNALIGNED++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \+ || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \+ || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \+ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \+ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \+ || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \+ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define SLJIT_UNALIGNED 1+#endif++#endif /* !SLJIT_UNALIGNED */++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+/* Auto detect SSE2 support using CPUID.+ On 64 bit x86 cpus, sse2 must be present. */+#define SLJIT_DETECT_SSE2 1+#endif++/*****************************************************************************************/+/* Calling convention of functions generated by SLJIT or called from the generated code. */+/*****************************************************************************************/++#ifndef SLJIT_FUNC++#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) \+ || !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)++#define SLJIT_FUNC++#elif defined(__GNUC__) && !defined(__APPLE__)++#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)+#define SLJIT_FUNC __attribute__ ((fastcall))+#define SLJIT_X86_32_FASTCALL 1+#else+#define SLJIT_FUNC+#endif /* gcc >= 3.4 */++#elif defined(_MSC_VER)++#define SLJIT_FUNC __fastcall+#define SLJIT_X86_32_FASTCALL 1++#elif defined(__BORLANDC__)++#define SLJIT_FUNC __msfastcall+#define SLJIT_X86_32_FASTCALL 1++#else /* Unknown compiler. */++/* The cdecl calling convention is usually the x86 default. */+#define SLJIT_FUNC++#endif /* SLJIT_USE_CDECL_CALLING_CONVENTION */++#endif /* !SLJIT_FUNC */++#ifndef SLJIT_INDIRECT_CALL+#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (!defined _CALL_ELF || _CALL_ELF == 1)) \+ || ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && defined _AIX)+/* It seems certain ppc compilers use an indirect addressing for functions+ which makes things complicated. */+#define SLJIT_INDIRECT_CALL 1+#endif+#endif /* SLJIT_INDIRECT_CALL */++/* The offset which needs to be substracted from the return address to+determine the next executed instruction after return. */+#ifndef SLJIT_RETURN_ADDRESS_OFFSET+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+#define SLJIT_RETURN_ADDRESS_OFFSET 8+#else+#define SLJIT_RETURN_ADDRESS_OFFSET 0+#endif+#endif /* SLJIT_RETURN_ADDRESS_OFFSET */++/***************************************************/+/* Functions of the built-in executable allocator. */+/***************************************************/++#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)+SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size);+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);+#define SLJIT_BUILTIN_MALLOC_EXEC(size, exec_allocator_data) sljit_malloc_exec(size)+#define SLJIT_BUILTIN_FREE_EXEC(ptr, exec_allocator_data) sljit_free_exec(ptr)++#ifndef SLJIT_MALLOC_EXEC+#define SLJIT_MALLOC_EXEC(size, exec_allocator_data) SLJIT_BUILTIN_MALLOC_EXEC((size), (exec_allocator_data))+#endif /* SLJIT_MALLOC_EXEC */++#ifndef SLJIT_FREE_EXEC+#define SLJIT_FREE_EXEC(ptr, exec_allocator_data) SLJIT_BUILTIN_FREE_EXEC((ptr), (exec_allocator_data))+#endif /* SLJIT_FREE_EXEC */++#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)+SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);+#define SLJIT_EXEC_OFFSET(ptr) sljit_exec_offset(ptr)+#else+#define SLJIT_EXEC_OFFSET(ptr) 0+#endif++#endif /* SLJIT_EXECUTABLE_ALLOCATOR */++/**********************************************/+/* Registers and locals offset determination. */+/**********************************************/++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)++#define SLJIT_NUMBER_OF_REGISTERS 12+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9+#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)+#define SLJIT_PREF_SHIFT_REG SLJIT_R2++#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)++#define SLJIT_NUMBER_OF_REGISTERS 13+#ifndef _WIN64+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 6+#define SLJIT_LOCALS_OFFSET_BASE 0+#else /* _WIN64 */+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8+#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)+#endif /* !_WIN64 */+#define SLJIT_PREF_SHIFT_REG SLJIT_R3++#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)++#define SLJIT_NUMBER_OF_REGISTERS 12+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8+#define SLJIT_LOCALS_OFFSET_BASE 0++#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)++#define SLJIT_NUMBER_OF_REGISTERS 12+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8+#define SLJIT_LOCALS_OFFSET_BASE 0++#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)++#define SLJIT_NUMBER_OF_REGISTERS 26+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10+#define SLJIT_LOCALS_OFFSET_BASE 0++#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)++#define SLJIT_NUMBER_OF_REGISTERS 23+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 17+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX)+#define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * sizeof(sljit_sw))+#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+/* Add +1 for double alignment. */+#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1) * sizeof(sljit_sw))+#else+#define SLJIT_LOCALS_OFFSET_BASE (3 * sizeof(sljit_sw))+#endif /* SLJIT_CONFIG_PPC_64 || _AIX */++#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)++#define SLJIT_NUMBER_OF_REGISTERS 21+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define SLJIT_LOCALS_OFFSET_BASE (4 * sizeof(sljit_sw))+#else+#define SLJIT_LOCALS_OFFSET_BASE 0+#endif++#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)++#define SLJIT_NUMBER_OF_REGISTERS 18+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 14+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+/* saved registers (16), return struct pointer (1), space for 6 argument words (1),+ 4th double arg (2), double alignment (1). */+#define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * sizeof(sljit_sw))+#endif++#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)++#define SLJIT_NUMBER_OF_REGISTERS 10+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 5+#define SLJIT_LOCALS_OFFSET_BASE 0++#elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)++#define SLJIT_NUMBER_OF_REGISTERS 0+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 0+#define SLJIT_LOCALS_OFFSET_BASE 0++#endif++#define SLJIT_LOCALS_OFFSET (SLJIT_LOCALS_OFFSET_BASE)++#define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \+ (SLJIT_NUMBER_OF_REGISTERS - SLJIT_NUMBER_OF_SAVED_REGISTERS)++#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 6+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && (defined _WIN64)+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 1+#else+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0+#endif++#define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \+ (SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)++/*************************************/+/* Debug and verbose related macros. */+/*************************************/++#if (defined SLJIT_DEBUG && SLJIT_DEBUG)++#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)++/* SLJIT_HALT_PROCESS must halt the process. */+#ifndef SLJIT_HALT_PROCESS+#define SLJIT_HALT_PROCESS() \+ abort();+#endif /* !SLJIT_HALT_PROCESS */++#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */++/* Feel free to redefine these two macros. */+#ifndef SLJIT_ASSERT++#define SLJIT_ASSERT(x) \+ do { \+ if (SLJIT_UNLIKELY(!(x))) { \+ printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \+ SLJIT_HALT_PROCESS(); \+ } \+ } while (0)++#endif /* !SLJIT_ASSERT */++#ifndef SLJIT_UNREACHABLE++#define SLJIT_UNREACHABLE() \+ do { \+ printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \+ SLJIT_HALT_PROCESS(); \+ } while (0)++#endif /* !SLJIT_UNREACHABLE */++#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */++/* Forcing empty, but valid statements. */+#undef SLJIT_ASSERT+#undef SLJIT_UNREACHABLE++#define SLJIT_ASSERT(x) \+ do { } while (0)+#define SLJIT_UNREACHABLE() \+ do { } while (0)++#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */++#ifndef SLJIT_COMPILE_ASSERT++#define SLJIT_COMPILE_ASSERT(x, description) \+ switch(0) { case 0: case ((x) ? 1 : 0): break; }++#endif /* !SLJIT_COMPILE_ASSERT */++#ifdef __cplusplus+} /* extern "C" */+#endif++#endif /* SLJIT_CONFIG_INTERNAL_H_ */
+ src/c/pcre2/src/sljit/sljitExecAllocator.c view
@@ -0,0 +1,385 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/*+ This file contains a simple executable memory allocator++ It is assumed, that executable code blocks are usually medium (or sometimes+ large) memory blocks, and the allocator is not too frequently called (less+ optimized than other allocators). Thus, using it as a generic allocator is+ not suggested.++ How does it work:+ Memory is allocated in continuous memory areas called chunks by alloc_chunk()+ Chunk format:+ [ block ][ block ] ... [ block ][ block terminator ]++ All blocks and the block terminator is started with block_header. The block+ header contains the size of the previous and the next block. These sizes+ can also contain special values.+ Block size:+ 0 - The block is a free_block, with a different size member.+ 1 - The block is a block terminator.+ n - The block is used at the moment, and the value contains its size.+ Previous block size:+ 0 - This is the first block of the memory chunk.+ n - The size of the previous block.++ Using these size values we can go forward or backward on the block chain.+ The unused blocks are stored in a chain list pointed by free_blocks. This+ list is useful if we need to find a suitable memory area when the allocator+ is called.++ When a block is freed, the new free block is connected to its adjacent free+ blocks if possible.++ [ free block ][ used block ][ free block ]+ and "used block" is freed, the three blocks are connected together:+ [ one big free block ]+*/++/* --------------------------------------------------------------------- */+/* System (OS) functions */+/* --------------------------------------------------------------------- */++/* 64 KByte. */+#define CHUNK_SIZE 0x10000++/*+ alloc_chunk / free_chunk :+ * allocate executable system memory chunks+ * the size is always divisible by CHUNK_SIZE+ SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK :+ * provided as part of sljitUtils+ * only the allocator requires this lock, sljit is fully thread safe+ as it only uses local variables+*/++#ifdef _WIN32++static SLJIT_INLINE void* alloc_chunk(sljit_uw size)+{+ return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);+}++static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)+{+ SLJIT_UNUSED_ARG(size);+ VirtualFree(chunk, 0, MEM_RELEASE);+}++#else++#ifdef __APPLE__+#ifdef MAP_ANON+/* Configures TARGET_OS_OSX when appropriate */+#include <TargetConditionals.h>++#if TARGET_OS_OSX && defined(MAP_JIT)+#include <sys/utsname.h>+#endif /* TARGET_OS_OSX && MAP_JIT */++#ifdef MAP_JIT++/*+ On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a+ version where it's OK to have more than one JIT block.+ On non-macOS systems, returns MAP_JIT if it is defined.+*/+static SLJIT_INLINE int get_map_jit_flag()+{+#if TARGET_OS_OSX+ sljit_sw page_size = get_page_alignment() + 1;+ void *ptr;+ static int map_jit_flag = -1;++ /*+ The following code is thread safe because multiple initialization+ sets map_jit_flag to the same value and the code has no side-effects.+ Changing the kernel version witout system restart is (very) unlikely.+ */+ if (map_jit_flag == -1) {+ struct utsname name;++ map_jit_flag = 0;+ uname(&name);++ /* Kernel version for 10.14.0 (Mojave) */+ if (atoi(name.release) >= 18) {+ /* Only use MAP_JIT if a hardened runtime is used */++ ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);++ if (ptr == MAP_FAILED) {+ map_jit_flag = MAP_JIT;+ } else {+ munmap(ptr, page_size);+ }+ }+ }++ return map_jit_flag;+#else /* !TARGET_OS_OSX */+ return MAP_JIT;+#endif /* TARGET_OS_OSX */+}++#endif /* MAP_JIT */+#endif /* MAP_ANON */+#endif /* __APPLE__ */++static SLJIT_INLINE void* alloc_chunk(sljit_uw size)+{+ void *retval;+ const int prot = PROT_READ | PROT_WRITE | PROT_EXEC;++#ifdef MAP_ANON++ int flags = MAP_PRIVATE | MAP_ANON;++#ifdef MAP_JIT+ flags |= get_map_jit_flag();+#endif++ retval = mmap(NULL, size, prot, flags, -1, 0);+#else /* !MAP_ANON */+ if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero()))+ return NULL;++ retval = mmap(NULL, size, prot, MAP_PRIVATE, dev_zero, 0);+#endif /* MAP_ANON */++ if (retval == MAP_FAILED)+ retval = NULL;+ else {+ if (mprotect(retval, size, prot) < 0) {+ munmap(retval, size);+ retval = NULL;+ }+ }++ return retval;+}++static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)+{+ munmap(chunk, size);+}++#endif++/* --------------------------------------------------------------------- */+/* Common functions */+/* --------------------------------------------------------------------- */++#define CHUNK_MASK (~(CHUNK_SIZE - 1))++struct block_header {+ sljit_uw size;+ sljit_uw prev_size;+};++struct free_block {+ struct block_header header;+ struct free_block *next;+ struct free_block *prev;+ sljit_uw size;+};++#define AS_BLOCK_HEADER(base, offset) \+ ((struct block_header*)(((sljit_u8*)base) + offset))+#define AS_FREE_BLOCK(base, offset) \+ ((struct free_block*)(((sljit_u8*)base) + offset))+#define MEM_START(base) ((void*)(((sljit_u8*)base) + sizeof(struct block_header)))+#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7)++static struct free_block* free_blocks;+static sljit_uw allocated_size;+static sljit_uw total_size;++static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)+{+ free_block->header.size = 0;+ free_block->size = size;++ free_block->next = free_blocks;+ free_block->prev = NULL;+ if (free_blocks)+ free_blocks->prev = free_block;+ free_blocks = free_block;+}++static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)+{+ if (free_block->next)+ free_block->next->prev = free_block->prev;++ if (free_block->prev)+ free_block->prev->next = free_block->next;+ else {+ SLJIT_ASSERT(free_blocks == free_block);+ free_blocks = free_block->next;+ }+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)+{+ struct block_header *header;+ struct block_header *next_header;+ struct free_block *free_block;+ sljit_uw chunk_size;++ SLJIT_ALLOCATOR_LOCK();+ if (size < (64 - sizeof(struct block_header)))+ size = (64 - sizeof(struct block_header));+ size = ALIGN_SIZE(size);++ free_block = free_blocks;+ while (free_block) {+ if (free_block->size >= size) {+ chunk_size = free_block->size;+ if (chunk_size > size + 64) {+ /* We just cut a block from the end of the free block. */+ chunk_size -= size;+ free_block->size = chunk_size;+ header = AS_BLOCK_HEADER(free_block, chunk_size);+ header->prev_size = chunk_size;+ AS_BLOCK_HEADER(header, size)->prev_size = size;+ }+ else {+ sljit_remove_free_block(free_block);+ header = (struct block_header*)free_block;+ size = chunk_size;+ }+ allocated_size += size;+ header->size = size;+ SLJIT_ALLOCATOR_UNLOCK();+ return MEM_START(header);+ }+ free_block = free_block->next;+ }++ chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK;+ header = (struct block_header*)alloc_chunk(chunk_size);+ if (!header) {+ SLJIT_ALLOCATOR_UNLOCK();+ return NULL;+ }++ chunk_size -= sizeof(struct block_header);+ total_size += chunk_size;++ header->prev_size = 0;+ if (chunk_size > size + 64) {+ /* Cut the allocated space into a free and a used block. */+ allocated_size += size;+ header->size = size;+ chunk_size -= size;++ free_block = AS_FREE_BLOCK(header, size);+ free_block->header.prev_size = size;+ sljit_insert_free_block(free_block, chunk_size);+ next_header = AS_BLOCK_HEADER(free_block, chunk_size);+ }+ else {+ /* All space belongs to this allocation. */+ allocated_size += chunk_size;+ header->size = chunk_size;+ next_header = AS_BLOCK_HEADER(header, chunk_size);+ }+ next_header->size = 1;+ next_header->prev_size = chunk_size;+ SLJIT_ALLOCATOR_UNLOCK();+ return MEM_START(header);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)+{+ struct block_header *header;+ struct free_block* free_block;++ SLJIT_ALLOCATOR_LOCK();+ header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));+ allocated_size -= header->size;++ /* Connecting free blocks together if possible. */++ /* If header->prev_size == 0, free_block will equal to header.+ In this case, free_block->header.size will be > 0. */+ free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);+ if (SLJIT_UNLIKELY(!free_block->header.size)) {+ free_block->size += header->size;+ header = AS_BLOCK_HEADER(free_block, free_block->size);+ header->prev_size = free_block->size;+ }+ else {+ free_block = (struct free_block*)header;+ sljit_insert_free_block(free_block, header->size);+ }++ header = AS_BLOCK_HEADER(free_block, free_block->size);+ if (SLJIT_UNLIKELY(!header->size)) {+ free_block->size += ((struct free_block*)header)->size;+ sljit_remove_free_block((struct free_block*)header);+ header = AS_BLOCK_HEADER(free_block, free_block->size);+ header->prev_size = free_block->size;+ }++ /* The whole chunk is free. */+ if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {+ /* If this block is freed, we still have (allocated_size / 2) free space. */+ if (total_size - free_block->size > (allocated_size * 3 / 2)) {+ total_size -= free_block->size;+ sljit_remove_free_block(free_block);+ free_chunk(free_block, free_block->size + sizeof(struct block_header));+ }+ }++ SLJIT_ALLOCATOR_UNLOCK();+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)+{+ struct free_block* free_block;+ struct free_block* next_free_block;++ SLJIT_ALLOCATOR_LOCK();++ free_block = free_blocks;+ while (free_block) {+ next_free_block = free_block->next;+ if (!free_block->header.prev_size && + AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {+ total_size -= free_block->size;+ sljit_remove_free_block(free_block);+ free_chunk(free_block, free_block->size + sizeof(struct block_header));+ }+ free_block = next_free_block;+ }++ SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks));+ SLJIT_ALLOCATOR_UNLOCK();+}
+ src/c/pcre2/src/sljit/sljitLir.c view
@@ -0,0 +1,2702 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++#include "sljitLir.h"++#ifdef _WIN32++#include <windows.h>++#endif /* _WIN32 */++#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)++/* These libraries are needed for the macros below. */+#include <stdlib.h>+#include <string.h>++#endif /* SLJIT_STD_MACROS_DEFINED */++#define CHECK_ERROR() \+ do { \+ if (SLJIT_UNLIKELY(compiler->error)) \+ return compiler->error; \+ } while (0)++#define CHECK_ERROR_PTR() \+ do { \+ if (SLJIT_UNLIKELY(compiler->error)) \+ return NULL; \+ } while (0)++#define FAIL_IF(expr) \+ do { \+ if (SLJIT_UNLIKELY(expr)) \+ return compiler->error; \+ } while (0)++#define PTR_FAIL_IF(expr) \+ do { \+ if (SLJIT_UNLIKELY(expr)) \+ return NULL; \+ } while (0)++#define FAIL_IF_NULL(ptr) \+ do { \+ if (SLJIT_UNLIKELY(!(ptr))) { \+ compiler->error = SLJIT_ERR_ALLOC_FAILED; \+ return SLJIT_ERR_ALLOC_FAILED; \+ } \+ } while (0)++#define PTR_FAIL_IF_NULL(ptr) \+ do { \+ if (SLJIT_UNLIKELY(!(ptr))) { \+ compiler->error = SLJIT_ERR_ALLOC_FAILED; \+ return NULL; \+ } \+ } while (0)++#define PTR_FAIL_WITH_EXEC_IF(ptr) \+ do { \+ if (SLJIT_UNLIKELY(!(ptr))) { \+ compiler->error = SLJIT_ERR_EX_ALLOC_FAILED; \+ return NULL; \+ } \+ } while (0)++#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)++#define VARIABLE_FLAG_SHIFT (10)+#define VARIABLE_FLAG_MASK (0x3f << VARIABLE_FLAG_SHIFT)+#define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT)++#define GET_OPCODE(op) \+ ((op) & ~(SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))++#define HAS_FLAGS(op) \+ ((op) & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))++#define GET_ALL_FLAGS(op) \+ ((op) & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))++#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+#define TYPE_CAST_NEEDED(op) \+ ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32)+#else+#define TYPE_CAST_NEEDED(op) \+ ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16)+#endif++#define BUF_SIZE 4096++#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)+#define ABUF_SIZE 2048+#else+#define ABUF_SIZE 4096+#endif++/* Parameter parsing. */+#define REG_MASK 0x3f+#define OFFS_REG(reg) (((reg) >> 8) & REG_MASK)+#define OFFS_REG_MASK (REG_MASK << 8)+#define TO_OFFS_REG(reg) ((reg) << 8)+/* When reg cannot be unused. */+#define FAST_IS_REG(reg) ((reg) <= REG_MASK)+/* When reg can be unused. */+#define SLOW_IS_REG(reg) ((reg) > 0 && (reg) <= REG_MASK)++/* Mask for argument types. */+#define SLJIT_DEF_MASK ((1 << SLJIT_DEF_SHIFT) - 1)++/* Jump flags. */+#define JUMP_LABEL 0x1+#define JUMP_ADDR 0x2+/* SLJIT_REWRITABLE_JUMP is 0x1000. */++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+# define PATCH_MB 0x4+# define PATCH_MW 0x8+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+# define PATCH_MD 0x10+#endif+# define TYPE_SHIFT 13+#endif++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+# define IS_BL 0x4+# define PATCH_B 0x8+#endif++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+# define CPOOL_SIZE 512+#endif++#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+# define IS_COND 0x04+# define IS_BL 0x08+ /* conditional + imm8 */+# define PATCH_TYPE1 0x10+ /* conditional + imm20 */+# define PATCH_TYPE2 0x20+ /* IT + imm24 */+# define PATCH_TYPE3 0x30+ /* imm11 */+# define PATCH_TYPE4 0x40+ /* imm24 */+# define PATCH_TYPE5 0x50+ /* BL + imm24 */+# define PATCH_BL 0x60+ /* 0xf00 cc code for branches */+#endif++#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+# define IS_COND 0x004+# define IS_CBZ 0x008+# define IS_BL 0x010+# define PATCH_B 0x020+# define PATCH_COND 0x040+# define PATCH_ABS48 0x080+# define PATCH_ABS64 0x100+#endif++#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)+# define IS_COND 0x004+# define IS_CALL 0x008+# define PATCH_B 0x010+# define PATCH_ABS_B 0x020+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+# define PATCH_ABS32 0x040+# define PATCH_ABS48 0x080+#endif+# define REMOVE_COND 0x100+#endif++#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+# define IS_MOVABLE 0x004+# define IS_JAL 0x008+# define IS_CALL 0x010+# define IS_BIT26_COND 0x020+# define IS_BIT16_COND 0x040+# define IS_BIT23_COND 0x080++# define IS_COND (IS_BIT26_COND | IS_BIT16_COND | IS_BIT23_COND)++# define PATCH_B 0x100+# define PATCH_J 0x200++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+# define PATCH_ABS32 0x400+# define PATCH_ABS48 0x800+#endif++ /* instruction types */+# define MOVABLE_INS 0+ /* 1 - 31 last destination register */+ /* no destination (i.e: store) */+# define UNMOVABLE_INS 32+ /* FPU status register */+# define FCSR_FCC 33+#endif++#if (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)+# define IS_JAL 0x04+# define IS_COND 0x08++# define PATCH_B 0x10+# define PATCH_J 0x20+#endif++#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+# define IS_MOVABLE 0x04+# define IS_COND 0x08+# define IS_CALL 0x10++# define PATCH_B 0x20+# define PATCH_CALL 0x40++ /* instruction types */+# define MOVABLE_INS 0+ /* 1 - 31 last destination register */+ /* no destination (i.e: store) */+# define UNMOVABLE_INS 32++# define DST_INS_MASK 0xff++ /* ICC_SET is the same as SET_FLAGS. */+# define ICC_IS_SET (1 << 23)+# define FCC_IS_SET (1 << 24)+#endif++/* Stack management. */++#define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) \+ (((scratches < SLJIT_NUMBER_OF_SCRATCH_REGISTERS ? 0 : (scratches - SLJIT_NUMBER_OF_SCRATCH_REGISTERS)) + \+ (saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? saveds : SLJIT_NUMBER_OF_SAVED_REGISTERS) + \+ extra) * sizeof(sljit_sw))++#define ADJUST_LOCAL_OFFSET(p, i) \+ if ((p) == (SLJIT_MEM1(SLJIT_SP))) \+ (i) += SLJIT_LOCALS_OFFSET;++#endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */++/* Utils can still be used even if SLJIT_CONFIG_UNSUPPORTED is set. */+#include "sljitUtils.c"++#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)++#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)++#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)+#include "sljitProtExecAllocator.c"+#elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)+#include "sljitWXExecAllocator.c"+#else+#include "sljitExecAllocator.c"+#endif++#endif++#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)+#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr) + (exec_offset))+#else+#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr))+#endif++#ifndef SLJIT_UPDATE_WX_FLAGS+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)+#endif++/* Argument checking features. */++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)++/* Returns with error when an invalid argument is passed. */++#define CHECK_ARGUMENT(x) \+ do { \+ if (SLJIT_UNLIKELY(!(x))) \+ return 1; \+ } while (0)++#define CHECK_RETURN_TYPE sljit_s32+#define CHECK_RETURN_OK return 0++#define CHECK(x) \+ do { \+ if (SLJIT_UNLIKELY(x)) { \+ compiler->error = SLJIT_ERR_BAD_ARGUMENT; \+ return SLJIT_ERR_BAD_ARGUMENT; \+ } \+ } while (0)++#define CHECK_PTR(x) \+ do { \+ if (SLJIT_UNLIKELY(x)) { \+ compiler->error = SLJIT_ERR_BAD_ARGUMENT; \+ return NULL; \+ } \+ } while (0)++#define CHECK_REG_INDEX(x) \+ do { \+ if (SLJIT_UNLIKELY(x)) { \+ return -2; \+ } \+ } while (0)++#elif (defined SLJIT_DEBUG && SLJIT_DEBUG)++/* Assertion failure occures if an invalid argument is passed. */+#undef SLJIT_ARGUMENT_CHECKS+#define SLJIT_ARGUMENT_CHECKS 1++#define CHECK_ARGUMENT(x) SLJIT_ASSERT(x)+#define CHECK_RETURN_TYPE void+#define CHECK_RETURN_OK return+#define CHECK(x) x+#define CHECK_PTR(x) x+#define CHECK_REG_INDEX(x) x++#elif (defined SLJIT_VERBOSE && SLJIT_VERBOSE)++/* Arguments are not checked. */+#define CHECK_RETURN_TYPE void+#define CHECK_RETURN_OK return+#define CHECK(x) x+#define CHECK_PTR(x) x+#define CHECK_REG_INDEX(x) x++#else++/* Arguments are not checked. */+#define CHECK(x)+#define CHECK_PTR(x)+#define CHECK_REG_INDEX(x)++#endif /* SLJIT_ARGUMENT_CHECKS */++/* --------------------------------------------------------------------- */+/* Public functions */+/* --------------------------------------------------------------------- */++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+#define SLJIT_NEEDS_COMPILER_INIT 1+static sljit_s32 compiler_initialized = 0;+/* A thread safe initialization. */+static void init_compiler(void);+#endif++SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data)+{+ struct sljit_compiler *compiler = (struct sljit_compiler*)SLJIT_MALLOC(sizeof(struct sljit_compiler), allocator_data);+ if (!compiler)+ return NULL;+ SLJIT_ZEROMEM(compiler, sizeof(struct sljit_compiler));++ SLJIT_COMPILE_ASSERT(+ sizeof(sljit_s8) == 1 && sizeof(sljit_u8) == 1+ && sizeof(sljit_s16) == 2 && sizeof(sljit_u16) == 2+ && sizeof(sljit_s32) == 4 && sizeof(sljit_u32) == 4+ && (sizeof(sljit_p) == 4 || sizeof(sljit_p) == 8)+ && sizeof(sljit_p) <= sizeof(sljit_sw)+ && (sizeof(sljit_sw) == 4 || sizeof(sljit_sw) == 8)+ && (sizeof(sljit_uw) == 4 || sizeof(sljit_uw) == 8),+ invalid_integer_types);+ SLJIT_COMPILE_ASSERT(SLJIT_I32_OP == SLJIT_F32_OP,+ int_op_and_single_op_must_be_the_same);+ SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_F32_OP,+ rewritable_jump_and_single_op_must_not_be_the_same);+ SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_EQUAL_F64 & 0x1) && !(SLJIT_JUMP & 0x1),+ conditional_flags_must_be_even_numbers);++ /* Only the non-zero members must be set. */+ compiler->error = SLJIT_SUCCESS;++ compiler->allocator_data = allocator_data;+ compiler->exec_allocator_data = exec_allocator_data;+ compiler->buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data);+ compiler->abuf = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, allocator_data);++ if (!compiler->buf || !compiler->abuf) {+ if (compiler->buf)+ SLJIT_FREE(compiler->buf, allocator_data);+ if (compiler->abuf)+ SLJIT_FREE(compiler->abuf, allocator_data);+ SLJIT_FREE(compiler, allocator_data);+ return NULL;+ }++ compiler->buf->next = NULL;+ compiler->buf->used_size = 0;+ compiler->abuf->next = NULL;+ compiler->abuf->used_size = 0;++ compiler->scratches = -1;+ compiler->saveds = -1;+ compiler->fscratches = -1;+ compiler->fsaveds = -1;+ compiler->local_size = -1;++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ compiler->args = -1;+#endif++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ compiler->cpool = (sljit_uw*)SLJIT_MALLOC(CPOOL_SIZE * sizeof(sljit_uw)+ + CPOOL_SIZE * sizeof(sljit_u8), allocator_data);+ if (!compiler->cpool) {+ SLJIT_FREE(compiler->buf, allocator_data);+ SLJIT_FREE(compiler->abuf, allocator_data);+ SLJIT_FREE(compiler, allocator_data);+ return NULL;+ }+ compiler->cpool_unique = (sljit_u8*)(compiler->cpool + CPOOL_SIZE);+ compiler->cpool_diff = 0xffffffff;+#endif++#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+ compiler->delay_slot = UNMOVABLE_INS;+#endif++#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ compiler->delay_slot = UNMOVABLE_INS;+#endif++#if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT)+ if (!compiler_initialized) {+ init_compiler();+ compiler_initialized = 1;+ }+#endif++ return compiler;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf;+ struct sljit_memory_fragment *curr;+ void *allocator_data = compiler->allocator_data;+ SLJIT_UNUSED_ARG(allocator_data);++ buf = compiler->buf;+ while (buf) {+ curr = buf;+ buf = buf->next;+ SLJIT_FREE(curr, allocator_data);+ }++ buf = compiler->abuf;+ while (buf) {+ curr = buf;+ buf = buf->next;+ SLJIT_FREE(curr, allocator_data);+ }++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ SLJIT_FREE(compiler->cpool, allocator_data);+#endif+ SLJIT_FREE(compiler, allocator_data);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler)+{+ if (compiler->error == SLJIT_SUCCESS)+ compiler->error = SLJIT_ERR_ALLOC_FAILED;+}++#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)+{+ /* Remove thumb mode flag. */+ SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~0x1), exec_allocator_data);+}+#elif (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)+{+ /* Resolve indirection. */+ code = (void*)(*(sljit_uw*)code);+ SLJIT_FREE_EXEC(code, exec_allocator_data);+}+#else+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)+{+ SLJIT_FREE_EXEC(code, exec_allocator_data);+}+#endif++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)+{+ if (SLJIT_LIKELY(!!jump) && SLJIT_LIKELY(!!label)) {+ jump->flags &= ~JUMP_ADDR;+ jump->flags |= JUMP_LABEL;+ jump->u.label = label;+ }+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)+{+ if (SLJIT_LIKELY(!!jump)) {+ jump->flags &= ~JUMP_LABEL;+ jump->flags |= JUMP_ADDR;+ jump->u.target = target;+ }+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label)+{+ if (SLJIT_LIKELY(!!put_label))+ put_label->label = label;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(current_flags);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_I32_OP | SLJIT_SET_Z)) == 0) {+ compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_I32_OP | SLJIT_SET_Z));+ }+#endif+}++/* --------------------------------------------------------------------- */+/* Private functions */+/* --------------------------------------------------------------------- */++static void* ensure_buf(struct sljit_compiler *compiler, sljit_uw size)+{+ sljit_u8 *ret;+ struct sljit_memory_fragment *new_frag;++ SLJIT_ASSERT(size <= 256);+ if (compiler->buf->used_size + size <= (BUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {+ ret = compiler->buf->memory + compiler->buf->used_size;+ compiler->buf->used_size += size;+ return ret;+ }+ new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, compiler->allocator_data);+ PTR_FAIL_IF_NULL(new_frag);+ new_frag->next = compiler->buf;+ compiler->buf = new_frag;+ new_frag->used_size = size;+ return new_frag->memory;+}++static void* ensure_abuf(struct sljit_compiler *compiler, sljit_uw size)+{+ sljit_u8 *ret;+ struct sljit_memory_fragment *new_frag;++ SLJIT_ASSERT(size <= 256);+ if (compiler->abuf->used_size + size <= (ABUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {+ ret = compiler->abuf->memory + compiler->abuf->used_size;+ compiler->abuf->used_size += size;+ return ret;+ }+ new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, compiler->allocator_data);+ PTR_FAIL_IF_NULL(new_frag);+ new_frag->next = compiler->abuf;+ compiler->abuf = new_frag;+ new_frag->used_size = size;+ return new_frag->memory;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size)+{+ CHECK_ERROR_PTR();++#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+ if (size <= 0 || size > 128)+ return NULL;+ size = (size + 7) & ~7;+#else+ if (size <= 0 || size > 64)+ return NULL;+ size = (size + 3) & ~3;+#endif+ return ensure_abuf(compiler, size);+}++static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf = compiler->buf;+ struct sljit_memory_fragment *prev = NULL;+ struct sljit_memory_fragment *tmp;++ do {+ tmp = buf->next;+ buf->next = prev;+ prev = buf;+ buf = tmp;+ } while (buf != NULL);++ compiler->buf = prev;+}++static SLJIT_INLINE sljit_s32 get_arg_count(sljit_s32 arg_types)+{+ sljit_s32 arg_count = 0;++ arg_types >>= SLJIT_DEF_SHIFT;+ while (arg_types) {+ arg_count++;+ arg_types >>= SLJIT_DEF_SHIFT;+ }++ return arg_count;+}++#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)++static SLJIT_INLINE sljit_uw compute_next_addr(struct sljit_label *label, struct sljit_jump *jump,+ struct sljit_const *const_, struct sljit_put_label *put_label)+{+ sljit_uw result = ~(sljit_uw)0;++ if (label)+ result = label->size;++ if (jump && jump->addr < result)+ result = jump->addr;++ if (const_ && const_->addr < result)+ result = const_->addr;++ if (put_label && put_label->addr < result)+ result = put_label->addr;++ return result;+}++#endif /* !SLJIT_CONFIG_X86 */++static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ SLJIT_UNUSED_ARG(args);+ SLJIT_UNUSED_ARG(local_size);++ compiler->options = options;+ compiler->scratches = scratches;+ compiler->saveds = saveds;+ compiler->fscratches = fscratches;+ compiler->fsaveds = fsaveds;+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->logical_local_size = local_size;+#endif+}++static SLJIT_INLINE void set_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ SLJIT_UNUSED_ARG(args);+ SLJIT_UNUSED_ARG(local_size);++ compiler->options = options;+ compiler->scratches = scratches;+ compiler->saveds = saveds;+ compiler->fscratches = fscratches;+ compiler->fsaveds = fsaveds;+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->logical_local_size = local_size;+#endif+}++static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler)+{+ label->next = NULL;+ label->size = compiler->size;+ if (compiler->last_label)+ compiler->last_label->next = label;+ else+ compiler->labels = label;+ compiler->last_label = label;+}++static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_s32 flags)+{+ jump->next = NULL;+ jump->flags = flags;+ if (compiler->last_jump)+ compiler->last_jump->next = jump;+ else+ compiler->jumps = jump;+ compiler->last_jump = jump;+}++static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_compiler *compiler)+{+ const_->next = NULL;+ const_->addr = compiler->size;+ if (compiler->last_const)+ compiler->last_const->next = const_;+ else+ compiler->consts = const_;+ compiler->last_const = const_;+}++static SLJIT_INLINE void set_put_label(struct sljit_put_label *put_label, struct sljit_compiler *compiler, sljit_uw offset)+{+ put_label->next = NULL;+ put_label->label = NULL;+ put_label->addr = compiler->size - offset;+ put_label->flags = 0;+ if (compiler->last_put_label)+ compiler->last_put_label->next = put_label;+ else+ compiler->put_labels = put_label;+ compiler->last_put_label = put_label;+}++#define ADDRESSING_DEPENDS_ON(exp, reg) \+ (((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)++#define FUNCTION_CHECK_IS_REG(r) \+ (((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \+ || ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0))++#define FUNCTION_CHECK_IS_FREG(fr) \+ (((fr) >= SLJIT_FR0 && (fr) < (SLJIT_FR0 + compiler->fscratches)) \+ || ((fr) > (SLJIT_FS0 - compiler->fsaveds) && (fr) <= SLJIT_FS0))++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+#define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8)+#else+#define CHECK_IF_VIRTUAL_REGISTER(p) 0+#endif++static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if (compiler->scratches == -1 || compiler->saveds == -1)+ return 0;++ if (!(p & SLJIT_MEM))+ return 0;++ if (!((p & REG_MASK) == SLJIT_UNUSED || FUNCTION_CHECK_IS_REG(p & REG_MASK)))+ return 0;++ if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK))+ return 0;++ if (p & OFFS_REG_MASK) {+ if ((p & REG_MASK) == SLJIT_UNUSED)+ return 0;++ if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p))))+ return 0;++ if (CHECK_IF_VIRTUAL_REGISTER(OFFS_REG(p)))+ return 0;++ if ((i & ~0x3) != 0)+ return 0;+ }++ return (p & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK)) == 0;+}++#define FUNCTION_CHECK_SRC_MEM(p, i) \+ CHECK_ARGUMENT(function_check_src_mem(compiler, p, i));++static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if (compiler->scratches == -1 || compiler->saveds == -1)+ return 0;++ if (FUNCTION_CHECK_IS_REG(p))+ return (i == 0);++ if (p == SLJIT_IMM)+ return 1;++ if (p == SLJIT_MEM1(SLJIT_SP))+ return (i >= 0 && i < compiler->logical_local_size);++ return function_check_src_mem(compiler, p, i);+}++#define FUNCTION_CHECK_SRC(p, i) \+ CHECK_ARGUMENT(function_check_src(compiler, p, i));++static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 unused)+{+ if (compiler->scratches == -1 || compiler->saveds == -1)+ return 0;++ if (FUNCTION_CHECK_IS_REG(p) || ((unused) && (p) == SLJIT_UNUSED))+ return (i == 0);++ if (p == SLJIT_MEM1(SLJIT_SP))+ return (i >= 0 && i < compiler->logical_local_size);++ return function_check_src_mem(compiler, p, i);+}++#define FUNCTION_CHECK_DST(p, i, unused) \+ CHECK_ARGUMENT(function_check_dst(compiler, p, i, unused));++static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if (compiler->scratches == -1 || compiler->saveds == -1)+ return 0;++ if (FUNCTION_CHECK_IS_FREG(p))+ return (i == 0);++ if (p == SLJIT_MEM1(SLJIT_SP))+ return (i >= 0 && i < compiler->logical_local_size);++ return function_check_src_mem(compiler, p, i);+}++#define FUNCTION_FCHECK(p, i) \+ CHECK_ARGUMENT(function_fcheck(compiler, p, i));++#endif /* SLJIT_ARGUMENT_CHECKS */++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)++SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose)+{+ compiler->verbose = verbose;+}++#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+#ifdef _WIN64+# define SLJIT_PRINT_D "I64"+#else+# define SLJIT_PRINT_D "l"+#endif+#else+# define SLJIT_PRINT_D ""+#endif++static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r)+{+ if (r < (SLJIT_R0 + compiler->scratches))+ fprintf(compiler->verbose, "r%d", r - SLJIT_R0);+ else if (r != SLJIT_SP)+ fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r);+ else+ fprintf(compiler->verbose, "sp");+}++static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r)+{+ if (r < (SLJIT_FR0 + compiler->fscratches))+ fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0);+ else+ fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r);+}++static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if ((p) & SLJIT_IMM)+ fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i));+ else if ((p) & SLJIT_MEM) {+ if ((p) & REG_MASK) {+ fputc('[', compiler->verbose);+ sljit_verbose_reg(compiler, (p) & REG_MASK);+ if ((p) & OFFS_REG_MASK) {+ fprintf(compiler->verbose, " + ");+ sljit_verbose_reg(compiler, OFFS_REG(p));+ if (i)+ fprintf(compiler->verbose, " * %d", 1 << (i));+ }+ else if (i)+ fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));+ fputc(']', compiler->verbose);+ }+ else+ fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));+ } else if (p)+ sljit_verbose_reg(compiler, p);+ else+ fprintf(compiler->verbose, "unused");+}++static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if ((p) & SLJIT_MEM) {+ if ((p) & REG_MASK) {+ fputc('[', compiler->verbose);+ sljit_verbose_reg(compiler, (p) & REG_MASK);+ if ((p) & OFFS_REG_MASK) {+ fprintf(compiler->verbose, " + ");+ sljit_verbose_reg(compiler, OFFS_REG(p));+ if (i)+ fprintf(compiler->verbose, "%d", 1 << (i));+ }+ else if (i)+ fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));+ fputc(']', compiler->verbose);+ }+ else+ fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));+ }+ else+ sljit_verbose_freg(compiler, p);+}++static const char* op0_names[] = {+ (char*)"breakpoint", (char*)"nop", (char*)"lmul.uw", (char*)"lmul.sw",+ (char*)"divmod.u", (char*)"divmod.s", (char*)"div.u", (char*)"div.s",+ (char*)"endbr", (char*)"skip_frames_before_return"+};++static const char* op1_names[] = {+ (char*)"", (char*)".u8", (char*)".s8", (char*)".u16",+ (char*)".s16", (char*)".u32", (char*)".s32", (char*)".p",+ (char*)"", (char*)".u8", (char*)".s8", (char*)".u16",+ (char*)".s16", (char*)".u32", (char*)".s32", (char*)".p",+ (char*)"not", (char*)"neg", (char*)"clz",+};++static const char* op2_names[] = {+ (char*)"add", (char*)"addc", (char*)"sub", (char*)"subc",+ (char*)"mul", (char*)"and", (char*)"or", (char*)"xor",+ (char*)"shl", (char*)"lshr", (char*)"ashr",+};++static const char* op_src_names[] = {+ (char*)"fast_return", (char*)"skip_frames_before_fast_return",+ (char*)"prefetch_l1", (char*)"prefetch_l2",+ (char*)"prefetch_l3", (char*)"prefetch_once",+};++static const char* fop1_names[] = {+ (char*)"mov", (char*)"conv", (char*)"conv", (char*)"conv",+ (char*)"conv", (char*)"conv", (char*)"cmp", (char*)"neg",+ (char*)"abs",+};++static const char* fop2_names[] = {+ (char*)"add", (char*)"sub", (char*)"mul", (char*)"div"+};++#define JUMP_POSTFIX(type) \+ ((type & 0xff) <= SLJIT_MUL_NOT_OVERFLOW ? ((type & SLJIT_I32_OP) ? "32" : "") \+ : ((type & 0xff) <= SLJIT_ORDERED_F64 ? ((type & SLJIT_F32_OP) ? ".f32" : ".f64") : ""))++static char* jump_names[] = {+ (char*)"equal", (char*)"not_equal",+ (char*)"less", (char*)"greater_equal",+ (char*)"greater", (char*)"less_equal",+ (char*)"sig_less", (char*)"sig_greater_equal",+ (char*)"sig_greater", (char*)"sig_less_equal",+ (char*)"overflow", (char*)"not_overflow",+ (char*)"mul_overflow", (char*)"mul_not_overflow",+ (char*)"carry", (char*)"",+ (char*)"equal", (char*)"not_equal",+ (char*)"less", (char*)"greater_equal",+ (char*)"greater", (char*)"less_equal",+ (char*)"unordered", (char*)"ordered",+ (char*)"jump", (char*)"fast_call",+ (char*)"call", (char*)"call.cdecl"+};++static char* call_arg_names[] = {+ (char*)"void", (char*)"sw", (char*)"uw", (char*)"s32", (char*)"u32", (char*)"f32", (char*)"f64"+};++#endif /* SLJIT_VERBOSE */++/* --------------------------------------------------------------------- */+/* Arch dependent */+/* --------------------------------------------------------------------- */++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ struct sljit_jump *jump;+#endif++ SLJIT_UNUSED_ARG(compiler);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(compiler->size > 0);+ jump = compiler->jumps;+ while (jump) {+ /* All jumps have target. */+ CHECK_ARGUMENT(jump->flags & (JUMP_LABEL | JUMP_ADDR));+ jump = jump->next;+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ sljit_s32 types, arg_count, curr_type;+#endif++ SLJIT_UNUSED_ARG(compiler);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT));+ CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);+ CHECK_ARGUMENT((arg_types & SLJIT_DEF_MASK) == 0);++ types = (arg_types >> SLJIT_DEF_SHIFT);+ arg_count = 0;+ while (types != 0 && arg_count < 3) {+ curr_type = (types & SLJIT_DEF_MASK);+ CHECK_ARGUMENT(curr_type == SLJIT_ARG_TYPE_SW || curr_type == SLJIT_ARG_TYPE_UW);+ arg_count++;+ types >>= SLJIT_DEF_SHIFT;+ }+ CHECK_ARGUMENT(arg_count <= saveds && types == 0);++ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " enter options:%s args[", (options & SLJIT_F64_ALIGNMENT) ? "f64_align" : "");++ arg_types >>= SLJIT_DEF_SHIFT;+ while (arg_types) {+ fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);+ arg_types >>= SLJIT_DEF_SHIFT;+ if (arg_types)+ fprintf(compiler->verbose, ",");+ }++ fprintf(compiler->verbose, "] scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n",+ scratches, saveds, fscratches, fsaveds, local_size);+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ sljit_s32 types, arg_count, curr_type;+#endif++ SLJIT_UNUSED_ARG(compiler);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT));+ CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);++ types = (arg_types >> SLJIT_DEF_SHIFT);+ arg_count = 0;+ while (types != 0 && arg_count < 3) {+ curr_type = (types & SLJIT_DEF_MASK);+ CHECK_ARGUMENT(curr_type == SLJIT_ARG_TYPE_SW || curr_type == SLJIT_ARG_TYPE_UW);+ arg_count++;+ types >>= SLJIT_DEF_SHIFT;+ }+ CHECK_ARGUMENT(arg_count <= saveds && types == 0);++ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " set_context options:%s args[", (options & SLJIT_F64_ALIGNMENT) ? "f64_align" : "");++ arg_types >>= SLJIT_DEF_SHIFT;+ while (arg_types) {+ fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);+ arg_types >>= SLJIT_DEF_SHIFT;+ if (arg_types)+ fprintf(compiler->verbose, ",");+ }++ fprintf(compiler->verbose, "] scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n",+ scratches, saveds, fscratches, fsaveds, local_size);+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(compiler->scratches >= 0);+ if (op != SLJIT_UNUSED) {+ CHECK_ARGUMENT(op >= SLJIT_MOV && op <= SLJIT_MOV_P);+ FUNCTION_CHECK_SRC(src, srcw);+ }+ else+ CHECK_ARGUMENT(src == 0 && srcw == 0);+ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (op == SLJIT_UNUSED)+ fprintf(compiler->verbose, " return\n");+ else {+ fprintf(compiler->verbose, " return%s ", op1_names[op - SLJIT_OP1_BASE]);+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ FUNCTION_CHECK_DST(dst, dstw, 0);+ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " fast_enter ");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW)+ || ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW)+ || (op >= SLJIT_ENDBR && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN));+ CHECK_ARGUMENT(GET_OPCODE(op) < SLJIT_LMUL_UW || GET_OPCODE(op) >= SLJIT_ENDBR || compiler->scratches >= 2);+ if ((GET_OPCODE(op) >= SLJIT_LMUL_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN)+ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose))+ {+ fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);+ if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) {+ fprintf(compiler->verbose, (op & SLJIT_I32_OP) ? "32" : "w");+ }+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ);++ switch (GET_OPCODE(op)) {+ case SLJIT_NOT:+ /* Only SLJIT_I32_OP and SLJIT_SET_Z are allowed. */+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));+ break;+ case SLJIT_NEG:+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)+ || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);+ break;+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_P:+ /* Nothing allowed */+ CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ break;+ default:+ /* Only SLJIT_I32_OP is allowed. */+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ break;+ }++ FUNCTION_CHECK_DST(dst, dstw, HAS_FLAGS(op));+ FUNCTION_CHECK_SRC(src, srcw);++ if (GET_OPCODE(op) >= SLJIT_NOT) {+ CHECK_ARGUMENT(src != SLJIT_IMM);+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));+ }+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (GET_OPCODE(op) <= SLJIT_MOV_P)+ {+ fprintf(compiler->verbose, " mov%s%s ", !(op & SLJIT_I32_OP) ? "" : "32",+ (op != SLJIT_MOV32) ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : "");+ }+ else+ {+ fprintf(compiler->verbose, " %s%s%s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & SLJIT_I32_OP) ? "" : "32",+ !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",+ !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);+ }++ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ASHR);++ switch (GET_OPCODE(op)) {+ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ case SLJIT_SHL:+ case SLJIT_LSHR:+ case SLJIT_ASHR:+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));+ break;+ case SLJIT_MUL:+ CHECK_ARGUMENT(!(op & SLJIT_SET_Z));+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)+ || GET_FLAG_TYPE(op) == SLJIT_MUL_OVERFLOW);+ break;+ case SLJIT_ADD:+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)+ || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)+ || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);+ break;+ case SLJIT_SUB:+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)+ || (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_OVERFLOW)+ || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));+ break;+ case SLJIT_ADDC:+ case SLJIT_SUBC:+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)+ || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));+ CHECK_ARGUMENT((compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY));+ CHECK_ARGUMENT((op & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP));+ break;+ default:+ SLJIT_UNREACHABLE();+ break;+ }++ FUNCTION_CHECK_DST(dst, dstw, HAS_FLAGS(op));+ FUNCTION_CHECK_SRC(src1, src1w);+ FUNCTION_CHECK_SRC(src2, src2w);+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_I32_OP) ? "" : "32",+ !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",+ !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(op >= SLJIT_FAST_RETURN && op <= SLJIT_PREFETCH_ONCE);+ FUNCTION_CHECK_SRC(src, srcw);++ if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN)+ {+ CHECK_ARGUMENT(src != SLJIT_IMM);+ compiler->last_flags = 0;+ }+ else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE)+ {+ CHECK_ARGUMENT(src & SLJIT_MEM);+ }+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s ", op_src_names[op - SLJIT_OP_SRC_BASE]);+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 reg)+{+ SLJIT_UNUSED_ARG(reg);+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS);+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_float_register_index(sljit_s32 reg)+{+ SLJIT_UNUSED_ARG(reg);+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size)+{+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ int i;+#endif++ SLJIT_UNUSED_ARG(compiler);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(instruction);++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+ CHECK_ARGUMENT(size > 0 && size < 16);+#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+ CHECK_ARGUMENT((size == 2 && (((sljit_sw)instruction) & 0x1) == 0)+ || (size == 4 && (((sljit_sw)instruction) & 0x3) == 0));+#else+ CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0);+#endif++ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " op_custom");+ for (i = 0; i < size; i++)+ fprintf(compiler->verbose, " 0x%x", ((sljit_u8*)instruction)[i]);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV_F64 && GET_OPCODE(op) <= SLJIT_ABS_F64);+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ FUNCTION_FCHECK(src, srcw);+ FUNCTION_FCHECK(dst, dstw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)+ fprintf(compiler->verbose, " %s%s ", fop1_names[SLJIT_CONV_F64_FROM_F32 - SLJIT_FOP1_BASE],+ (op & SLJIT_F32_OP) ? ".f32.from.f64" : ".f64.from.f32");+ else+ fprintf(compiler->verbose, " %s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],+ (op & SLJIT_F32_OP) ? ".f32" : ".f64");++ sljit_verbose_fparam(compiler, dst, dstw);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));+#endif++ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_CMP_F64);+ CHECK_ARGUMENT(!(op & SLJIT_SET_Z));+ CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK)+ || (GET_FLAG_TYPE(op) >= SLJIT_EQUAL_F64 && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_F64));+ FUNCTION_FCHECK(src1, src1w);+ FUNCTION_FCHECK(src2, src2w);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64");+ if (op & VARIABLE_FLAG_MASK) {+ fprintf(compiler->verbose, ".%s_f", jump_names[GET_FLAG_TYPE(op)]);+ }+ fprintf(compiler->verbose, " ");+ sljit_verbose_fparam(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CONV_S32_FROM_F64);+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ FUNCTION_FCHECK(src, srcw);+ FUNCTION_CHECK_DST(dst, dstw, 0);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],+ (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? ".s32" : ".sw",+ (op & SLJIT_F32_OP) ? ".f32" : ".f64");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_SW && GET_OPCODE(op) <= SLJIT_CONV_F64_FROM_S32);+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ FUNCTION_CHECK_SRC(src, srcw);+ FUNCTION_FCHECK(dst, dstw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],+ (op & SLJIT_F32_OP) ? ".f32" : ".f64",+ (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? ".s32" : ".sw");+ sljit_verbose_fparam(compiler, dst, dstw);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD_F64 && GET_OPCODE(op) <= SLJIT_DIV_F64);+ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));+ FUNCTION_FCHECK(src1, src1w);+ FUNCTION_FCHECK(src2, src2w);+ FUNCTION_FCHECK(dst, dstw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64");+ sljit_verbose_fparam(compiler, dst, dstw);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compiler *compiler)+{+ SLJIT_UNUSED_ARG(compiler);++ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->last_flags = 0;+#endif++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose))+ fprintf(compiler->verbose, "label:\n");+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));+ CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1));+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL);+ CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_I32_OP));++ if ((type & 0xff) < SLJIT_JUMP) {+ if ((type & 0xff) <= SLJIT_NOT_ZERO)+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);+ else+ CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)+ || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)+ || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));+ CHECK_ARGUMENT((type & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP));+ }+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose))+ fprintf(compiler->verbose, " jump%s %s%s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",+ jump_names[type & 0xff], JUMP_POSTFIX(type));+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ sljit_s32 i, types, curr_type, scratches, fscratches;++ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));+ CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL);++ types = arg_types;+ scratches = 0;+ fscratches = 0;+ for (i = 0; i < 5; i++) {+ curr_type = (types & SLJIT_DEF_MASK);+ CHECK_ARGUMENT(curr_type <= SLJIT_ARG_TYPE_F64);+ if (i > 0) {+ if (curr_type == 0) {+ break;+ }+ if (curr_type >= SLJIT_ARG_TYPE_F32)+ fscratches++;+ else+ scratches++;+ } else {+ if (curr_type >= SLJIT_ARG_TYPE_F32) {+ CHECK_ARGUMENT(compiler->fscratches > 0);+ } else if (curr_type >= SLJIT_ARG_TYPE_SW) {+ CHECK_ARGUMENT(compiler->scratches > 0);+ }+ }+ types >>= SLJIT_DEF_SHIFT;+ }+ CHECK_ARGUMENT(compiler->scratches >= scratches);+ CHECK_ARGUMENT(compiler->fscratches >= fscratches);+ CHECK_ARGUMENT(types == 0);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s%s ret[%s", jump_names[type & 0xff],+ !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", call_arg_names[arg_types & SLJIT_DEF_MASK]);++ arg_types >>= SLJIT_DEF_SHIFT;+ if (arg_types) {+ fprintf(compiler->verbose, "], args[");+ do {+ fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);+ arg_types >>= SLJIT_DEF_SHIFT;+ if (arg_types)+ fprintf(compiler->verbose, ",");+ } while (arg_types);+ }+ fprintf(compiler->verbose, "]\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_SIG_LESS_EQUAL);+ FUNCTION_CHECK_SRC(src1, src1w);+ FUNCTION_CHECK_SRC(src2, src2w);+ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " cmp%s %s%s, ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",+ jump_names[type & 0xff], (type & SLJIT_I32_OP) ? "32" : "");+ sljit_verbose_param(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_F32_OP)));+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL_F64 && (type & 0xff) <= SLJIT_ORDERED_F64);+ FUNCTION_FCHECK(src1, src1w);+ FUNCTION_FCHECK(src2, src2w);+ compiler->last_flags = 0;+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " fcmp%s %s%s, ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",+ jump_names[type & 0xff], (type & SLJIT_F32_OP) ? ".f32" : ".f64");+ sljit_verbose_fparam(compiler, src1, src1w);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_fparam(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src, sljit_sw srcw)+{+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {+ compiler->skip_checks = 0;+ CHECK_RETURN_OK;+ }++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_FAST_CALL);+ FUNCTION_CHECK_SRC(src, srcw);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " ijump.%s ", jump_names[type]);+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ sljit_s32 i, types, curr_type, scratches, fscratches;++ CHECK_ARGUMENT(type == SLJIT_CALL || type == SLJIT_CALL_CDECL);+ FUNCTION_CHECK_SRC(src, srcw);++ types = arg_types;+ scratches = 0;+ fscratches = 0;+ for (i = 0; i < 5; i++) {+ curr_type = (types & SLJIT_DEF_MASK);+ CHECK_ARGUMENT(curr_type <= SLJIT_ARG_TYPE_F64);+ if (i > 0) {+ if (curr_type == 0) {+ break;+ }+ if (curr_type >= SLJIT_ARG_TYPE_F32)+ fscratches++;+ else+ scratches++;+ } else {+ if (curr_type >= SLJIT_ARG_TYPE_F32) {+ CHECK_ARGUMENT(compiler->fscratches > 0);+ } else if (curr_type >= SLJIT_ARG_TYPE_SW) {+ CHECK_ARGUMENT(compiler->scratches > 0);+ }+ }+ types >>= SLJIT_DEF_SHIFT;+ }+ CHECK_ARGUMENT(compiler->scratches >= scratches);+ CHECK_ARGUMENT(compiler->fscratches >= fscratches);+ CHECK_ARGUMENT(types == 0);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff],+ !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", call_arg_names[arg_types & SLJIT_DEF_MASK]);++ arg_types >>= SLJIT_DEF_SHIFT;+ if (arg_types) {+ fprintf(compiler->verbose, "], args[");+ do {+ fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);+ arg_types >>= SLJIT_DEF_SHIFT;+ if (arg_types)+ fprintf(compiler->verbose, ",");+ } while (arg_types);+ }+ fprintf(compiler->verbose, "], ");+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 type)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);+ CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1));+ CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32+ || (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR));+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));++ if ((type & 0xff) <= SLJIT_NOT_ZERO)+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);+ else+ CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)+ || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)+ || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));++ FUNCTION_CHECK_DST(dst, dstw, 0);++ if (GET_OPCODE(op) >= SLJIT_ADD)+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " flags%s %s%s, ",+ !(op & SLJIT_SET_Z) ? "" : ".z",+ GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],+ GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_I32_OP) ? "32" : ""));+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", %s%s\n", jump_names[type & 0xff], JUMP_POSTFIX(type));+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);++ CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP));+ if (src != SLJIT_IMM) {+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src));+ CHECK_ARGUMENT(srcw == 0);+ }++ if ((type & 0xff) <= SLJIT_NOT_ZERO)+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);+ else+ CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)+ || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW)+ || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " cmov%s %s%s, ",+ !(dst_reg & SLJIT_I32_OP) ? "" : "32",+ jump_names[type & 0xff], JUMP_POSTFIX(type));+ sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);+ CHECK_ARGUMENT(!(type & SLJIT_I32_OP) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P));+ CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));+ CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));+ CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);++ FUNCTION_CHECK_SRC_MEM(mem, memw);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));++ CHECK_ARGUMENT((mem & REG_MASK) != SLJIT_UNUSED && (mem & REG_MASK) != reg);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED)+ fprintf(compiler->verbose, " //");++ fprintf(compiler->verbose, " mem%s.%s%s%s ",+ !(type & SLJIT_I32_OP) ? "" : "32",+ (type & SLJIT_MEM_STORE) ? "st" : "ld",+ op1_names[(type & 0xff) - SLJIT_OP1_BASE],+ (type & SLJIT_MEM_PRE) ? ".pre" : ".post");+ sljit_verbose_reg(compiler, reg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, mem, memw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);+ CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));+ CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));+ CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);++ FUNCTION_CHECK_SRC_MEM(mem, memw);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg));+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED)+ fprintf(compiler->verbose, " //");++ fprintf(compiler->verbose, " fmem.%s%s%s ",+ (type & SLJIT_MEM_STORE) ? "st" : "ld",+ !(type & SLJIT_I32_OP) ? ".f64" : ".f32",+ (type & SLJIT_MEM_PRE) ? ".pre" : ".post");+ sljit_verbose_freg(compiler, freg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, mem, memw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)+{+ /* Any offset is allowed. */+ SLJIT_UNUSED_ARG(offset);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ FUNCTION_CHECK_DST(dst, dstw, 0);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " local_base ");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", offset);+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ SLJIT_UNUSED_ARG(init_value);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ FUNCTION_CHECK_DST(dst, dstw, 0);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " const ");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value);+ }+#endif+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ FUNCTION_CHECK_DST(dst, dstw, 0);+#endif+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " put_label ");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, "\n");+ }+#endif+ CHECK_RETURN_OK;+}++#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */++#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \+ SLJIT_COMPILE_ASSERT(!(SLJIT_CONV_SW_FROM_F64 & 0x1) && !(SLJIT_CONV_F64_FROM_SW & 0x1), \+ invalid_float_opcodes); \+ if (GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CMP_F64) { \+ if (GET_OPCODE(op) == SLJIT_CMP_F64) { \+ CHECK(check_sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw)); \+ ADJUST_LOCAL_OFFSET(dst, dstw); \+ ADJUST_LOCAL_OFFSET(src, srcw); \+ return sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw); \+ } \+ if ((GET_OPCODE(op) | 0x1) == SLJIT_CONV_S32_FROM_F64) { \+ CHECK(check_sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw)); \+ ADJUST_LOCAL_OFFSET(dst, dstw); \+ ADJUST_LOCAL_OFFSET(src, srcw); \+ return sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw); \+ } \+ CHECK(check_sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw)); \+ ADJUST_LOCAL_OFFSET(dst, dstw); \+ ADJUST_LOCAL_OFFSET(src, srcw); \+ return sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw); \+ } \+ CHECK(check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw)); \+ ADJUST_LOCAL_OFFSET(dst, dstw); \+ ADJUST_LOCAL_OFFSET(src, srcw);++static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ /* Return if don't need to do anything. */+ if (op == SLJIT_UNUSED)+ return SLJIT_SUCCESS;++#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+ /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */+ if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P))+ return SLJIT_SUCCESS;+#else+ if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P))+ return SLJIT_SUCCESS;+#endif++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ compiler->skip_checks = 1;+#endif+ return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);+}++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \+ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \+ || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \+ || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1))++static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+ struct sljit_label *label;+ struct sljit_jump *jump;+ sljit_s32 op = (dst_reg & SLJIT_I32_OP) ? SLJIT_MOV32 : SLJIT_MOV;++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ jump = sljit_emit_jump(compiler, type ^ 0x1);+ FAIL_IF(!jump);++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_I32_OP, 0, src, srcw));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ label = sljit_emit_label(compiler);+ FAIL_IF(!label);+ sljit_set_label(jump, label);+ return SLJIT_SUCCESS;+}++#endif++/* CPU description section */++#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)+#define SLJIT_CPUINFO_PART1 " 32bit ("+#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+#define SLJIT_CPUINFO_PART1 " 64bit ("+#else+#error "Internal error: CPU type info missing"+#endif++#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#define SLJIT_CPUINFO_PART2 "little endian + "+#elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)+#define SLJIT_CPUINFO_PART2 "big endian + "+#else+#error "Internal error: CPU type info missing"+#endif++#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)+#define SLJIT_CPUINFO_PART3 "unaligned)"+#else+#define SLJIT_CPUINFO_PART3 "aligned)"+#endif++#define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+# include "sljitNativeX86_common.c"+#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+# include "sljitNativeARM_32.c"+#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+# include "sljitNativeARM_32.c"+#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+# include "sljitNativeARM_T2_32.c"+#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+# include "sljitNativeARM_64.c"+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)+# include "sljitNativePPC_common.c"+#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+# include "sljitNativeMIPS_common.c"+#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)+# include "sljitNativeSPARC_common.c"+#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)+# include "sljitNativeTILEGX_64.c"+#endif++#if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ /* Default compare for most architectures. */+ sljit_s32 flags, tmp_src, condition;+ sljit_sw tmp_srcw;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));++ condition = type & 0xff;+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+ if ((condition == SLJIT_EQUAL || condition == SLJIT_NOT_EQUAL)) {+ if ((src1 & SLJIT_IMM) && !src1w) {+ src1 = src2;+ src1w = src2w;+ src2 = SLJIT_IMM;+ src2w = 0;+ }+ if ((src2 & SLJIT_IMM) && !src2w)+ return emit_cmp_to0(compiler, type, src1, src1w);+ }+#endif++ if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) {+ /* Immediate is prefered as second argument by most architectures. */+ switch (condition) {+ case SLJIT_LESS:+ condition = SLJIT_GREATER;+ break;+ case SLJIT_GREATER_EQUAL:+ condition = SLJIT_LESS_EQUAL;+ break;+ case SLJIT_GREATER:+ condition = SLJIT_LESS;+ break;+ case SLJIT_LESS_EQUAL:+ condition = SLJIT_GREATER_EQUAL;+ break;+ case SLJIT_SIG_LESS:+ condition = SLJIT_SIG_GREATER;+ break;+ case SLJIT_SIG_GREATER_EQUAL:+ condition = SLJIT_SIG_LESS_EQUAL;+ break;+ case SLJIT_SIG_GREATER:+ condition = SLJIT_SIG_LESS;+ break;+ case SLJIT_SIG_LESS_EQUAL:+ condition = SLJIT_SIG_GREATER_EQUAL;+ break;+ }++ type = condition | (type & (SLJIT_I32_OP | SLJIT_REWRITABLE_JUMP));+ tmp_src = src1;+ src1 = src2;+ src2 = tmp_src;+ tmp_srcw = src1w;+ src1w = src2w;+ src2w = tmp_srcw;+ }++ if (condition <= SLJIT_NOT_ZERO)+ flags = SLJIT_SET_Z;+ else+ flags = condition << VARIABLE_FLAG_SHIFT;++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ PTR_FAIL_IF(sljit_emit_op2(compiler, SLJIT_SUB | flags | (type & SLJIT_I32_OP),+ SLJIT_UNUSED, 0, src1, src1w, src2, src2w));+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));+}++#endif++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_I32_OP), src1, src1w, src2, src2w);++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ return sljit_emit_jump(compiler, type);+}++#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \+ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \+ && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(reg);+ SLJIT_UNUSED_ARG(mem);+ SLJIT_UNUSED_ARG(memw);++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ return SLJIT_ERR_UNSUPPORTED;+}++#endif++#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \+ && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(freg);+ SLJIT_UNUSED_ARG(mem);+ SLJIT_UNUSED_ARG(memw);++ CHECK_ERROR();+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));++ return SLJIT_ERR_UNSUPPORTED;+}++#endif++#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \+ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)+{+ CHECK_ERROR();+ CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));++ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ if (offset != 0)+ return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);+ return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0);+}++#endif++#else /* SLJIT_CONFIG_UNSUPPORTED */++/* Empty function bodies for those machines, which are not (yet) supported. */++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+ return "unsupported";+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data)+{+ SLJIT_UNUSED_ARG(allocator_data);+ SLJIT_UNUSED_ARG(exec_allocator_data);+ SLJIT_UNREACHABLE();+ return NULL;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNREACHABLE();+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNREACHABLE();+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(size);+ SLJIT_UNREACHABLE();+ return NULL;+}++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(verbose);+ SLJIT_UNREACHABLE();+}+#endif++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNREACHABLE();+ return NULL;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ SLJIT_UNUSED_ARG(feature_type);+ SLJIT_UNREACHABLE();+ return 0;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)+{+ SLJIT_UNUSED_ARG(code);+ SLJIT_UNUSED_ARG(exec_allocator_data);+ SLJIT_UNREACHABLE();+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(options);+ SLJIT_UNUSED_ARG(arg_types);+ SLJIT_UNUSED_ARG(scratches);+ SLJIT_UNUSED_ARG(saveds);+ SLJIT_UNUSED_ARG(fscratches);+ SLJIT_UNUSED_ARG(fsaveds);+ SLJIT_UNUSED_ARG(local_size);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(options);+ SLJIT_UNUSED_ARG(arg_types);+ SLJIT_UNUSED_ARG(scratches);+ SLJIT_UNUSED_ARG(saveds);+ SLJIT_UNUSED_ARG(fscratches);+ SLJIT_UNUSED_ARG(fsaveds);+ SLJIT_UNUSED_ARG(local_size);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(op);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(dst);+ SLJIT_UNUSED_ARG(dstw);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(op);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(op);+ SLJIT_UNUSED_ARG(dst);+ SLJIT_UNUSED_ARG(dstw);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(op);+ SLJIT_UNUSED_ARG(dst);+ SLJIT_UNUSED_ARG(dstw);+ SLJIT_UNUSED_ARG(src1);+ SLJIT_UNUSED_ARG(src1w);+ SLJIT_UNUSED_ARG(src2);+ SLJIT_UNUSED_ARG(src2w);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(op);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)+{+ SLJIT_UNREACHABLE();+ return reg;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(instruction);+ SLJIT_UNUSED_ARG(size);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(current_flags);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(op);+ SLJIT_UNUSED_ARG(dst);+ SLJIT_UNUSED_ARG(dstw);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(op);+ SLJIT_UNUSED_ARG(dst);+ SLJIT_UNUSED_ARG(dstw);+ SLJIT_UNUSED_ARG(src1);+ SLJIT_UNUSED_ARG(src1w);+ SLJIT_UNUSED_ARG(src2);+ SLJIT_UNUSED_ARG(src2w);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNREACHABLE();+ return NULL;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNREACHABLE();+ return NULL;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(arg_types);+ SLJIT_UNREACHABLE();+ return NULL;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(src1);+ SLJIT_UNUSED_ARG(src1w);+ SLJIT_UNUSED_ARG(src2);+ SLJIT_UNUSED_ARG(src2w);+ SLJIT_UNREACHABLE();+ return NULL;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(src1);+ SLJIT_UNUSED_ARG(src1w);+ SLJIT_UNUSED_ARG(src2);+ SLJIT_UNUSED_ARG(src2w);+ SLJIT_UNREACHABLE();+ return NULL;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)+{+ SLJIT_UNUSED_ARG(jump);+ SLJIT_UNUSED_ARG(label);+ SLJIT_UNREACHABLE();+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)+{+ SLJIT_UNUSED_ARG(jump);+ SLJIT_UNUSED_ARG(target);+ SLJIT_UNREACHABLE();+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label)+{+ SLJIT_UNUSED_ARG(put_label);+ SLJIT_UNUSED_ARG(label);+ SLJIT_UNREACHABLE();+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(arg_types);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 type)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(op);+ SLJIT_UNUSED_ARG(dst);+ SLJIT_UNUSED_ARG(dstw);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(dst_reg);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(reg);+ SLJIT_UNUSED_ARG(mem);+ SLJIT_UNUSED_ARG(memw);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(freg);+ SLJIT_UNUSED_ARG(mem);+ SLJIT_UNUSED_ARG(memw);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(dst);+ SLJIT_UNUSED_ARG(dstw);+ SLJIT_UNUSED_ARG(offset);+ SLJIT_UNREACHABLE();+ return SLJIT_ERR_UNSUPPORTED;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw initval)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(dst);+ SLJIT_UNUSED_ARG(dstw);+ SLJIT_UNUSED_ARG(initval);+ SLJIT_UNREACHABLE();+ return NULL;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(dst);+ SLJIT_UNUSED_ARG(dstw);+ return NULL;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ SLJIT_UNUSED_ARG(addr);+ SLJIT_UNUSED_ARG(new_target);+ SLJIT_UNUSED_ARG(executable_offset);+ SLJIT_UNREACHABLE();+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ SLJIT_UNUSED_ARG(addr);+ SLJIT_UNUSED_ARG(new_constant);+ SLJIT_UNUSED_ARG(executable_offset);+ SLJIT_UNREACHABLE();+}++#endif /* !SLJIT_CONFIG_UNSUPPORTED */
+ src/c/pcre2/src/sljit/sljitLir.h view
@@ -0,0 +1,1544 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++#ifndef SLJIT_LIR_H_+#define SLJIT_LIR_H_++/*+ ------------------------------------------------------------------------+ Stack-Less JIT compiler for multiple architectures (x86, ARM, PowerPC)+ ------------------------------------------------------------------------++ Short description+ Advantages:+ - The execution can be continued from any LIR instruction. In other+ words, it is possible to jump to any label from anywhere, even from+ a code fragment, which is compiled later, if both compiled code+ shares the same context. See sljit_emit_enter for more details+ - Supports self modifying code: target of (conditional) jump and call+ instructions and some constant values can be dynamically modified+ during runtime+ - although it is not suggested to do it frequently+ - can be used for inline caching: save an important value once+ in the instruction stream+ - since this feature limits the optimization possibilities, a+ special flag must be passed at compile time when these+ instructions are emitted+ - A fixed stack space can be allocated for local variables+ - The compiler is thread-safe+ - The compiler is highly configurable through preprocessor macros.+ You can disable unneeded features (multithreading in single+ threaded applications), and you can use your own system functions+ (including memory allocators). See sljitConfig.h+ Disadvantages:+ - No automatic register allocation, and temporary results are+ not stored on the stack. (hence the name comes)+ In practice:+ - This approach is very effective for interpreters+ - One of the saved registers typically points to a stack interface+ - It can jump to any exception handler anytime (even if it belongs+ to another function)+ - Hot paths can be modified during runtime reflecting the changes+ of the fastest execution path of the dynamic language+ - SLJIT supports complex memory addressing modes+ - mainly position and context independent code (except some cases)++ For valgrind users:+ - pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code"+*/++#if (defined SLJIT_HAVE_CONFIG_PRE && SLJIT_HAVE_CONFIG_PRE)+#include "sljitConfigPre.h"+#endif /* SLJIT_HAVE_CONFIG_PRE */++#include "sljitConfig.h"++/* The following header file defines useful macros for fine tuning+sljit based code generators. They are listed in the beginning+of sljitConfigInternal.h */++#include "sljitConfigInternal.h"++#if (defined SLJIT_HAVE_CONFIG_POST && SLJIT_HAVE_CONFIG_POST)+#include "sljitConfigPost.h"+#endif /* SLJIT_HAVE_CONFIG_POST */++#ifdef __cplusplus+extern "C" {+#endif++/* --------------------------------------------------------------------- */+/* Error codes */+/* --------------------------------------------------------------------- */++/* Indicates no error. */+#define SLJIT_SUCCESS 0+/* After the call of sljit_generate_code(), the error code of the compiler+ is set to this value to avoid future sljit calls (in debug mode at least).+ The complier should be freed after sljit_generate_code(). */+#define SLJIT_ERR_COMPILED 1+/* Cannot allocate non executable memory. */+#define SLJIT_ERR_ALLOC_FAILED 2+/* Cannot allocate executable memory.+ Only for sljit_generate_code() */+#define SLJIT_ERR_EX_ALLOC_FAILED 3+/* Return value for SLJIT_CONFIG_UNSUPPORTED placeholder architecture. */+#define SLJIT_ERR_UNSUPPORTED 4+/* An ivalid argument is passed to any SLJIT function. */+#define SLJIT_ERR_BAD_ARGUMENT 5+/* Dynamic code modification is not enabled. */+#define SLJIT_ERR_DYN_CODE_MOD 6++/* --------------------------------------------------------------------- */+/* Registers */+/* --------------------------------------------------------------------- */++/*+ Scratch (R) registers: registers whose may not preserve their values+ across function calls.++ Saved (S) registers: registers whose preserve their values across+ function calls.++ The scratch and saved register sets are overlap. The last scratch register+ is the first saved register, the one before the last is the second saved+ register, and so on.++ If an architecture provides two scratch and three saved registers,+ its scratch and saved register sets are the following:++ R0 | | R0 is always a scratch register+ R1 | | R1 is always a scratch register+ [R2] | S2 | R2 and S2 represent the same physical register+ [R3] | S1 | R3 and S1 represent the same physical register+ [R4] | S0 | R4 and S0 represent the same physical register++ Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS would be 2 and+ SLJIT_NUMBER_OF_SAVED_REGISTERS would be 3 for this architecture.++ Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 12+ and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 6. However, 6 registers+ are virtual on x86-32. See below.++ The purpose of this definition is convenience: saved registers can+ be used as extra scratch registers. For example four registers can+ be specified as scratch registers and the fifth one as saved register+ on the CPU above and any user code which requires four scratch+ registers can run unmodified. The SLJIT compiler automatically saves+ the content of the two extra scratch register on the stack. Scratch+ registers can also be preserved by saving their value on the stack+ but this needs to be done manually.++ Note: To emphasize that registers assigned to R2-R4 are saved+ registers, they are enclosed by square brackets.++ Note: sljit_emit_enter and sljit_set_context defines whether a register+ is S or R register. E.g: when 3 scratches and 1 saved is mapped+ by sljit_emit_enter, the allowed register set will be: R0-R2 and+ S0. Although S2 is mapped to the same position as R2, it does not+ available in the current configuration. Furthermore the S1 register+ is not available at all.+*/++/* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1+ or sljit_emit_op2 operations the result is discarded. Some status+ flags must be set when the destination is SLJIT_UNUSED, because the+ operation would have no effect otherwise. Other SLJIT operations do+ not support SLJIT_UNUSED as a destination operand. */+#define SLJIT_UNUSED 0++/* Scratch registers. */+#define SLJIT_R0 1+#define SLJIT_R1 2+#define SLJIT_R2 3+/* Note: on x86-32, R3 - R6 (same as S3 - S6) are emulated (they+ are allocated on the stack). These registers are called virtual+ and cannot be used for memory addressing (cannot be part of+ any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such+ limitation on other CPUs. See sljit_get_register_index(). */+#define SLJIT_R3 4+#define SLJIT_R4 5+#define SLJIT_R5 6+#define SLJIT_R6 7+#define SLJIT_R7 8+#define SLJIT_R8 9+#define SLJIT_R9 10+/* All R registers provided by the architecture can be accessed by SLJIT_R(i)+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_REGISTERS. */+#define SLJIT_R(i) (1 + (i))++/* Saved registers. */+#define SLJIT_S0 (SLJIT_NUMBER_OF_REGISTERS)+#define SLJIT_S1 (SLJIT_NUMBER_OF_REGISTERS - 1)+#define SLJIT_S2 (SLJIT_NUMBER_OF_REGISTERS - 2)+/* Note: on x86-32, S3 - S6 (same as R3 - R6) are emulated (they+ are allocated on the stack). These registers are called virtual+ and cannot be used for memory addressing (cannot be part of+ any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such+ limitation on other CPUs. See sljit_get_register_index(). */+#define SLJIT_S3 (SLJIT_NUMBER_OF_REGISTERS - 3)+#define SLJIT_S4 (SLJIT_NUMBER_OF_REGISTERS - 4)+#define SLJIT_S5 (SLJIT_NUMBER_OF_REGISTERS - 5)+#define SLJIT_S6 (SLJIT_NUMBER_OF_REGISTERS - 6)+#define SLJIT_S7 (SLJIT_NUMBER_OF_REGISTERS - 7)+#define SLJIT_S8 (SLJIT_NUMBER_OF_REGISTERS - 8)+#define SLJIT_S9 (SLJIT_NUMBER_OF_REGISTERS - 9)+/* All S registers provided by the architecture can be accessed by SLJIT_S(i)+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_REGISTERS. */+#define SLJIT_S(i) (SLJIT_NUMBER_OF_REGISTERS - (i))++/* Registers >= SLJIT_FIRST_SAVED_REG are saved registers. */+#define SLJIT_FIRST_SAVED_REG (SLJIT_S0 - SLJIT_NUMBER_OF_SAVED_REGISTERS + 1)++/* The SLJIT_SP provides direct access to the linear stack space allocated by+ sljit_emit_enter. It can only be used in the following form: SLJIT_MEM1(SLJIT_SP).+ The immediate offset is extended by the relative stack offset automatically.+ The sljit_get_local_base can be used to obtain the absolute offset. */+#define SLJIT_SP (SLJIT_NUMBER_OF_REGISTERS + 1)++/* Return with machine word. */++#define SLJIT_RETURN_REG SLJIT_R0++/* --------------------------------------------------------------------- */+/* Floating point registers */+/* --------------------------------------------------------------------- */++/* Each floating point register can store a 32 or a 64 bit precision+ value. The FR and FS register sets are overlap in the same way as R+ and S register sets. See above. */++/* Note: SLJIT_UNUSED as destination is not valid for floating point+ operations, since they cannot be used for setting flags. */++/* Floating point scratch registers. */+#define SLJIT_FR0 1+#define SLJIT_FR1 2+#define SLJIT_FR2 3+#define SLJIT_FR3 4+#define SLJIT_FR4 5+#define SLJIT_FR5 6+/* All FR registers provided by the architecture can be accessed by SLJIT_FR(i)+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_FLOAT_REGISTERS. */+#define SLJIT_FR(i) (1 + (i))++/* Floating point saved registers. */+#define SLJIT_FS0 (SLJIT_NUMBER_OF_FLOAT_REGISTERS)+#define SLJIT_FS1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1)+#define SLJIT_FS2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2)+#define SLJIT_FS3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 3)+#define SLJIT_FS4 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 4)+#define SLJIT_FS5 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 5)+/* All S registers provided by the architecture can be accessed by SLJIT_FS(i)+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS. */+#define SLJIT_FS(i) (SLJIT_NUMBER_OF_FLOAT_REGISTERS - (i))++/* Float registers >= SLJIT_FIRST_SAVED_FLOAT_REG are saved registers. */+#define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1)++/* --------------------------------------------------------------------- */+/* Argument type definitions */+/* --------------------------------------------------------------------- */++/* Argument type definitions.+ Used by SLJIT_[DEF_]ARGx and SLJIT_[DEF]_RET macros. */++#define SLJIT_ARG_TYPE_VOID 0+#define SLJIT_ARG_TYPE_SW 1+#define SLJIT_ARG_TYPE_UW 2+#define SLJIT_ARG_TYPE_S32 3+#define SLJIT_ARG_TYPE_U32 4+#define SLJIT_ARG_TYPE_F32 5+#define SLJIT_ARG_TYPE_F64 6++/* The following argument type definitions are used by sljit_emit_enter,+ sljit_set_context, sljit_emit_call, and sljit_emit_icall functions.+ The following return type definitions are used by sljit_emit_call+ and sljit_emit_icall functions.++ When a function is called, the first integer argument must be placed+ in SLJIT_R0, the second in SLJIT_R1, and so on. Similarly the first+ floating point argument must be placed in SLJIT_FR0, the second in+ SLJIT_FR1, and so on.++ Example function definition:+ sljit_f32 SLJIT_FUNC example_c_callback(sljit_sw arg_a,+ sljit_f64 arg_b, sljit_u32 arg_c, sljit_f32 arg_d);++ Argument type definition:+ SLJIT_DEF_RET(SLJIT_ARG_TYPE_F32)+ | SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_SW) | SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_F64)+ | SLJIT_DEF_ARG3(SLJIT_ARG_TYPE_U32) | SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_F32)++ Short form of argument type definition:+ SLJIT_RET(F32) | SLJIT_ARG1(SW) | SLJIT_ARG2(F64)+ | SLJIT_ARG3(S32) | SLJIT_ARG4(F32)++ Argument passing:+ arg_a must be placed in SLJIT_R0+ arg_c must be placed in SLJIT_R1+ arg_b must be placed in SLJIT_FR0+ arg_d must be placed in SLJIT_FR1++Note:+ The SLJIT_ARG_TYPE_VOID type is only supported by+ SLJIT_DEF_RET, and SLJIT_ARG_TYPE_VOID is also the+ default value when SLJIT_DEF_RET is not specified. */+#define SLJIT_DEF_SHIFT 4+#define SLJIT_DEF_RET(type) (type)+#define SLJIT_DEF_ARG1(type) ((type) << SLJIT_DEF_SHIFT)+#define SLJIT_DEF_ARG2(type) ((type) << (2 * SLJIT_DEF_SHIFT))+#define SLJIT_DEF_ARG3(type) ((type) << (3 * SLJIT_DEF_SHIFT))+#define SLJIT_DEF_ARG4(type) ((type) << (4 * SLJIT_DEF_SHIFT))++/* Short form of the macros above.++ For example the following definition:+ SLJIT_DEF_RET(SLJIT_ARG_TYPE_SW) | SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_F32)++ can be shortened to:+ SLJIT_RET(SW) | SLJIT_ARG1(F32)++Note:+ The VOID type is only supported by SLJIT_RET, and+ VOID is also the default value when SLJIT_RET is+ not specified. */+#define SLJIT_RET(type) SLJIT_DEF_RET(SLJIT_ARG_TYPE_ ## type)+#define SLJIT_ARG1(type) SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_ ## type)+#define SLJIT_ARG2(type) SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_ ## type)+#define SLJIT_ARG3(type) SLJIT_DEF_ARG3(SLJIT_ARG_TYPE_ ## type)+#define SLJIT_ARG4(type) SLJIT_DEF_ARG4(SLJIT_ARG_TYPE_ ## type)++/* --------------------------------------------------------------------- */+/* Main structures and functions */+/* --------------------------------------------------------------------- */++/*+ The following structures are private, and can be changed in the+ future. Keeping them here allows code inlining.+*/++struct sljit_memory_fragment {+ struct sljit_memory_fragment *next;+ sljit_uw used_size;+ /* Must be aligned to sljit_sw. */+ sljit_u8 memory[1];+};++struct sljit_label {+ struct sljit_label *next;+ sljit_uw addr;+ /* The maximum size difference. */+ sljit_uw size;+};++struct sljit_jump {+ struct sljit_jump *next;+ sljit_uw addr;+ sljit_uw flags;+ union {+ sljit_uw target;+ struct sljit_label *label;+ } u;+};++struct sljit_put_label {+ struct sljit_put_label *next;+ struct sljit_label *label;+ sljit_uw addr;+ sljit_uw flags;+};++struct sljit_const {+ struct sljit_const *next;+ sljit_uw addr;+};++struct sljit_compiler {+ sljit_s32 error;+ sljit_s32 options;++ struct sljit_label *labels;+ struct sljit_jump *jumps;+ struct sljit_put_label *put_labels;+ struct sljit_const *consts;+ struct sljit_label *last_label;+ struct sljit_jump *last_jump;+ struct sljit_const *last_const;+ struct sljit_put_label *last_put_label;++ void *allocator_data;+ void *exec_allocator_data;+ struct sljit_memory_fragment *buf;+ struct sljit_memory_fragment *abuf;++ /* Used scratch registers. */+ sljit_s32 scratches;+ /* Used saved registers. */+ sljit_s32 saveds;+ /* Used float scratch registers. */+ sljit_s32 fscratches;+ /* Used float saved registers. */+ sljit_s32 fsaveds;+ /* Local stack size. */+ sljit_s32 local_size;+ /* Code size. */+ sljit_uw size;+ /* Relative offset of the executable mapping from the writable mapping. */+ sljit_uw executable_offset;+ /* Executable size for statistical purposes. */+ sljit_uw executable_size;++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_s32 args;+ sljit_s32 locals_offset;+ sljit_s32 saveds_offset;+ sljit_s32 stack_tmp_size;+#endif++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_s32 mode32;+#ifdef _WIN64+ sljit_s32 locals_offset;+#endif+#endif++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ /* Constant pool handling. */+ sljit_uw *cpool;+ sljit_u8 *cpool_unique;+ sljit_uw cpool_diff;+ sljit_uw cpool_fill;+ /* Other members. */+ /* Contains pointer, "ldr pc, [...]" pairs. */+ sljit_uw patches;+#endif++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ /* Temporary fields. */+ sljit_uw shift_imm;+#endif++#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)+ sljit_sw imm;+#endif++#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+ sljit_s32 delay_slot;+ sljit_s32 cache_arg;+ sljit_sw cache_argw;+#endif++#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ sljit_s32 delay_slot;+ sljit_s32 cache_arg;+ sljit_sw cache_argw;+#endif++#if (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)+ sljit_s32 cache_arg;+ sljit_sw cache_argw;+#endif++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ FILE* verbose;+#endif++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)+ /* Flags specified by the last arithmetic instruction.+ It contains the type of the variable flag. */+ sljit_s32 last_flags;+ /* Local size passed to the functions. */+ sljit_s32 logical_local_size;+#endif++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ /* Trust arguments when the API function is called. */+ sljit_s32 skip_checks;+#endif+};++/* --------------------------------------------------------------------- */+/* Main functions */+/* --------------------------------------------------------------------- */++/* Creates an sljit compiler. The allocator_data is required by some+ custom memory managers. This pointer is passed to SLJIT_MALLOC+ and SLJIT_FREE macros. Most allocators (including the default+ one) ignores this value, and it is recommended to pass NULL+ as a dummy value for allocator_data. The exec_allocator_data+ has the same purpose but this one is passed to SLJIT_MALLOC_EXEC /+ SLJIT_MALLOC_FREE functions.++ Returns NULL if failed. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data);++/* Frees everything except the compiled machine code. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler);++/* Returns the current error code. If an error is occurred, future sljit+ calls which uses the same compiler argument returns early with the same+ error code. Thus there is no need for checking the error after every+ call, it is enough to do it before the code is compiled. Removing+ these checks increases the performance of the compiling process. */+static SLJIT_INLINE sljit_s32 sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }++/* Sets the compiler error code to SLJIT_ERR_ALLOC_FAILED except+ if an error was detected before. After the error code is set+ the compiler behaves as if the allocation failure happened+ during an sljit function call. This can greatly simplify error+ checking, since only the compiler status needs to be checked+ after the compilation. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler);++/*+ Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit,+ and <= 128 bytes on 64 bit architectures. The memory area is owned by the+ compiler, and freed by sljit_free_compiler. The returned pointer is+ sizeof(sljit_sw) aligned. Excellent for allocating small blocks during+ the compiling, and no need to worry about freeing them. The size is+ enough to contain at most 16 pointers. If the size is outside of the range,+ the function will return with NULL. However, this return value does not+ indicate that there is no more memory (does not set the current error code+ of the compiler to out-of-memory status).+*/+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size);++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+/* Passing NULL disables verbose. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose);+#endif++/*+ Create executable code from the sljit instruction stream. This is the final step+ of the code generation so no more instructions can be added after this call.+*/++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler);++/* Free executable code. */++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data);++/*+ When the protected executable allocator is used the JIT code is mapped+ twice. The first mapping has read/write and the second mapping has read/exec+ permissions. This function returns with the relative offset of the executable+ mapping using the writable mapping as the base after the machine code is+ successfully generated. The returned value is always 0 for the normal executable+ allocator, since it uses only one mapping with read/write/exec permissions.+ Dynamic code modifications requires this value.++ Before a successful code generation, this function returns with 0.+*/+static SLJIT_INLINE sljit_sw sljit_get_executable_offset(struct sljit_compiler *compiler) { return compiler->executable_offset; }++/*+ The executable memory consumption of the generated code can be retrieved by+ this function. The returned value can be used for statistical purposes.++ Before a successful code generation, this function returns with 0.+*/+static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; }++/* Returns with non-zero if the feature or limitation type passed as its+ argument is present on the current CPU.++ Some features (e.g. floating point operations) require hardware (CPU)+ support while others (e.g. move with update) are emulated if not available.+ However even if a feature is emulated, specialized code paths can be faster+ than the emulation. Some limitations are emulated as well so their general+ case is supported but it has extra performance costs. */++/* [Not emulated] Floating-point support is available. */+#define SLJIT_HAS_FPU 0+/* [Limitation] Some registers are virtual registers. */+#define SLJIT_HAS_VIRTUAL_REGISTERS 1+/* [Emulated] Has zero register (setting a memory location to zero is efficient). */+#define SLJIT_HAS_ZERO_REGISTER 2+/* [Emulated] Count leading zero is supported. */+#define SLJIT_HAS_CLZ 3+/* [Emulated] Conditional move is supported. */+#define SLJIT_HAS_CMOV 4+/* [Emulated] Conditional move is supported. */+#define SLJIT_HAS_PREFETCH 5++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+/* [Not emulated] SSE2 support is available on x86. */+#define SLJIT_HAS_SSE2 100+#endif++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type);++/* Instruction generation. Returns with any error code. If there is no+ error, they return with SLJIT_SUCCESS. */++/*+ The executable code is a function from the viewpoint of the C+ language. The function calls must obey to the ABI (Application+ Binary Interface) of the platform, which specify the purpose of+ machine registers and stack handling among other things. The+ sljit_emit_enter function emits the necessary instructions for+ setting up a new context for the executable code and moves function+ arguments to the saved registers. Furthermore the options argument+ can be used to pass configuration options to the compiler. The+ available options are listed before sljit_emit_enter.++ The function argument list is the combination of SLJIT_ARGx+ (SLJIT_DEF_ARG1) macros. Currently maximum 3 SW / UW+ (SLJIT_ARG_TYPE_SW / LJIT_ARG_TYPE_UW) arguments are supported.+ The first argument goes to SLJIT_S0, the second goes to SLJIT_S1+ and so on. The register set used by the function must be declared+ as well. The number of scratch and saved registers used by the+ function must be passed to sljit_emit_enter. Only R registers+ between R0 and "scratches" argument can be used later. E.g. if+ "scratches" is set to 2, the scratch register set will be limited+ to SLJIT_R0 and SLJIT_R1. The S registers and the floating point+ registers ("fscratches" and "fsaveds") are specified in a similar+ manner. The sljit_emit_enter is also capable of allocating a stack+ space for local variables. The "local_size" argument contains the+ size in bytes of this local area and its staring address is stored+ in SLJIT_SP. The memory area between SLJIT_SP (inclusive) and+ SLJIT_SP + local_size (exclusive) can be modified freely until+ the function returns. The stack space is not initialized.++ Note: the following conditions must met:+ 0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS+ 0 <= saveds <= SLJIT_NUMBER_OF_REGISTERS+ scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS+ 0 <= fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS+ 0 <= fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS+ fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS++ Note: every call of sljit_emit_enter and sljit_set_context+ overwrites the previous context.+*/++/* The absolute address returned by sljit_get_local_base with+offset 0 is aligned to sljit_f64. Otherwise it is aligned to sljit_sw. */+#define SLJIT_F64_ALIGNMENT 0x00000001++/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */+#define SLJIT_MAX_LOCAL_SIZE 65536++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size);++/* The machine code has a context (which contains the local stack space size,+ number of used registers, etc.) which initialized by sljit_emit_enter. Several+ functions (like sljit_emit_return) requres this context to be able to generate+ the appropriate code. However, some code fragments (like inline cache) may have+ no normal entry point so their context is unknown for the compiler. Their context+ can be provided to the compiler by the sljit_set_context function.++ Note: every call of sljit_emit_enter and sljit_set_context overwrites+ the previous context. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size);++/* Return from machine code. The op argument can be SLJIT_UNUSED which means the+ function does not return with anything or any opcode between SLJIT_MOV and+ SLJIT_MOV_P (see sljit_emit_op1). As for src and srcw they must be 0 if op+ is SLJIT_UNUSED, otherwise see below the description about source and+ destination arguments. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw);++/* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL).+ Both sljit_emit_fast_enter and SLJIT_FAST_RETURN operations preserve the+ values of all registers and stack frame. The return address is stored in the+ dst argument of sljit_emit_fast_enter, and this return address can be passed+ to SLJIT_FAST_RETURN to continue the execution after the fast call.++ Fast calls are cheap operations (usually only a single call instruction is+ emitted) but they do not preserve any registers. However the callee function+ can freely use / update any registers and stack values which can be+ efficiently exploited by various optimizations. Registers can be saved+ manually by the callee function if needed.++ Although returning to different address by SLJIT_FAST_RETURN is possible,+ this address usually cannot be predicted by the return address predictor of+ modern CPUs which may reduce performance. Furthermore certain security+ enhancement technologies such as Intel Control-flow Enforcement Technology+ (CET) may disallow returning to a different address.++ Flags: - (does not modify flags). */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);++/*+ Source and destination operands for arithmetical instructions+ imm - a simple immediate value (cannot be used as a destination)+ reg - any of the registers (immediate argument must be 0)+ [imm] - absolute immediate memory address+ [reg+imm] - indirect memory address+ [reg+(reg<<imm)] - indirect indexed memory address (shift must be between 0 and 3)+ useful for (byte, half, int, sljit_sw) array access+ (fully supported by both x86 and ARM architectures, and cheap operation on others)+*/++/*+ IMPORTANT NOTE: memory access MUST be naturally aligned unless+ SLJIT_UNALIGNED macro is defined and its value is 1.++ length | alignment+ ---------+-----------+ byte | 1 byte (any physical_address is accepted)+ half | 2 byte (physical_address & 0x1 == 0)+ int | 4 byte (physical_address & 0x3 == 0)+ word | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1+ | 8 byte if SLJIT_64BIT_ARCHITECTURE is defined and its value is 1+ pointer | size of sljit_p type (4 byte on 32 bit machines, 4 or 8 byte+ | on 64 bit machines)++ Note: Different architectures have different addressing limitations.+ A single instruction is enough for the following addressing+ modes. Other adrressing modes are emulated by instruction+ sequences. This information could help to improve those code+ generators which focuses only a few architectures.++ x86: [reg+imm], -2^32+1 <= imm <= 2^32-1 (full address space on x86-32)+ [reg+(reg<<imm)] is supported+ [imm], -2^32+1 <= imm <= 2^32-1 is supported+ Write-back is not supported+ arm: [reg+imm], -4095 <= imm <= 4095 or -255 <= imm <= 255 for signed+ bytes, any halfs or floating point values)+ [reg+(reg<<imm)] is supported+ Write-back is supported+ arm-t2: [reg+imm], -255 <= imm <= 4095+ [reg+(reg<<imm)] is supported+ Write back is supported only for [reg+imm], where -255 <= imm <= 255+ arm64: [reg+imm], -256 <= imm <= 255, 0 <= aligned imm <= 4095 * alignment+ [reg+(reg<<imm)] is supported+ Write back is supported only for [reg+imm], where -256 <= imm <= 255+ ppc: [reg+imm], -65536 <= imm <= 65535. 64 bit loads/stores and 32 bit+ signed load on 64 bit requires immediates divisible by 4.+ [reg+imm] is not supported for signed 8 bit values.+ [reg+reg] is supported+ Write-back is supported except for one instruction: 32 bit signed+ load with [reg+imm] addressing mode on 64 bit.+ mips: [reg+imm], -65536 <= imm <= 65535+ sparc: [reg+imm], -4096 <= imm <= 4095+ [reg+reg] is supported+*/++/* Macros for specifying operand types. */+#define SLJIT_MEM 0x80+#define SLJIT_MEM0() (SLJIT_MEM)+#define SLJIT_MEM1(r1) (SLJIT_MEM | (r1))+#define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 8))+#define SLJIT_IMM 0x40++/* Set 32 bit operation mode (I) on 64 bit CPUs. This option is ignored on+ 32 bit CPUs. When this option is set for an arithmetic operation, only+ the lower 32 bit of the input registers are used, and the CPU status+ flags are set according to the 32 bit result. Although the higher 32 bit+ of the input and the result registers are not defined by SLJIT, it might+ be defined by the CPU architecture (e.g. MIPS). To satisfy these CPU+ requirements all source registers must be the result of those operations+ where this option was also set. Memory loads read 32 bit values rather+ than 64 bit ones. In other words 32 bit and 64 bit operations cannot+ be mixed. The only exception is SLJIT_MOV32 and SLJIT_MOVU32 whose source+ register can hold any 32 or 64 bit value, and it is converted to a 32 bit+ compatible format first. This conversion is free (no instructions are+ emitted) on most CPUs. A 32 bit value can also be converted to a 64 bit+ value by SLJIT_MOV_S32 (sign extension) or SLJIT_MOV_U32 (zero extension).++ Note: memory addressing always uses 64 bit values on 64 bit systems so+ the result of a 32 bit operation must not be used with SLJIT_MEMx+ macros.++ This option is part of the instruction name, so there is no need to+ manually set it. E.g:++ SLJIT_ADD32 == (SLJIT_ADD | SLJIT_I32_OP) */+#define SLJIT_I32_OP 0x100++/* Set F32 (single) precision mode for floating-point computation. This+ option is similar to SLJIT_I32_OP, it just applies to floating point+ registers. When this option is passed, the CPU performs 32 bit floating+ point operations, rather than 64 bit one. Similar to SLJIT_I32_OP, all+ register arguments must be the result of those operations where this+ option was also set.++ This option is part of the instruction name, so there is no need to+ manually set it. E.g:++ SLJIT_MOV_F32 = (SLJIT_MOV_F64 | SLJIT_F32_OP)+ */+#define SLJIT_F32_OP SLJIT_I32_OP++/* Many CPUs (x86, ARM, PPC) have status flags which can be set according+ to the result of an operation. Other CPUs (MIPS) do not have status+ flags, and results must be stored in registers. To cover both architecture+ types efficiently only two flags are defined by SLJIT:++ * Zero (equal) flag: it is set if the result is zero+ * Variable flag: its value is defined by the last arithmetic operation++ SLJIT instructions can set any or both of these flags. The value of+ these flags is undefined if the instruction does not specify their value.+ The description of each instruction contains the list of allowed flag+ types.++ Example: SLJIT_ADD can set the Z, OVERFLOW, CARRY flags hence++ sljit_op2(..., SLJIT_ADD, ...)+ Both the zero and variable flags are undefined so they can+ have any value after the operation is completed.++ sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z, ...)+ Sets the zero flag if the result is zero, clears it otherwise.+ The variable flag is undefined.++ sljit_op2(..., SLJIT_ADD | SLJIT_SET_OVERFLOW, ...)+ Sets the variable flag if an integer overflow occurs, clears+ it otherwise. The zero flag is undefined.++ sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z | SLJIT_SET_CARRY, ...)+ Sets the zero flag if the result is zero, clears it otherwise.+ Sets the variable flag if unsigned overflow (carry) occurs,+ clears it otherwise.++ If an instruction (e.g. SLJIT_MOV) does not modify flags the flags are+ unchanged.++ Using these flags can reduce the number of emitted instructions. E.g. a+ fast loop can be implemented by decreasing a counter register and set the+ zero flag to jump back if the counter register has not reached zero.++ Motivation: although CPUs can set a large number of flags, usually their+ values are ignored or only one of them is used. Emulating a large number+ of flags on systems without flag register is complicated so SLJIT+ instructions must specify the flag they want to use and only that flag+ will be emulated. The last arithmetic instruction can be repeated if+ multiple flags need to be checked.+*/++/* Set Zero status flag. */+#define SLJIT_SET_Z 0x0200+/* Set the variable status flag if condition is true.+ See comparison types. */+#define SLJIT_SET(condition) ((condition) << 10)++/* Notes:+ - you cannot postpone conditional jump instructions except if noted that+ the instruction does not set flags (See: SLJIT_KEEP_FLAGS).+ - flag combinations: '|' means 'logical or'. */++/* Starting index of opcodes for sljit_emit_op0. */+#define SLJIT_OP0_BASE 0++/* Flags: - (does not modify flags)+ Note: breakpoint instruction is not supported by all architectures (e.g. ppc)+ It falls back to SLJIT_NOP in those cases. */+#define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0)+/* Flags: - (does not modify flags)+ Note: may or may not cause an extra cycle wait+ it can even decrease the runtime in a few cases. */+#define SLJIT_NOP (SLJIT_OP0_BASE + 1)+/* Flags: - (may destroy flags)+ Unsigned multiplication of SLJIT_R0 and SLJIT_R1.+ Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */+#define SLJIT_LMUL_UW (SLJIT_OP0_BASE + 2)+/* Flags: - (may destroy flags)+ Signed multiplication of SLJIT_R0 and SLJIT_R1.+ Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */+#define SLJIT_LMUL_SW (SLJIT_OP0_BASE + 3)+/* Flags: - (may destroy flags)+ Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.+ The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.+ Note: if SLJIT_R1 is 0, the behaviour is undefined. */+#define SLJIT_DIVMOD_UW (SLJIT_OP0_BASE + 4)+#define SLJIT_DIVMOD_U32 (SLJIT_DIVMOD_UW | SLJIT_I32_OP)+/* Flags: - (may destroy flags)+ Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.+ The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.+ Note: if SLJIT_R1 is 0, the behaviour is undefined.+ Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),+ the behaviour is undefined. */+#define SLJIT_DIVMOD_SW (SLJIT_OP0_BASE + 5)+#define SLJIT_DIVMOD_S32 (SLJIT_DIVMOD_SW | SLJIT_I32_OP)+/* Flags: - (may destroy flags)+ Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.+ The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.+ Note: if SLJIT_R1 is 0, the behaviour is undefined. */+#define SLJIT_DIV_UW (SLJIT_OP0_BASE + 6)+#define SLJIT_DIV_U32 (SLJIT_DIV_UW | SLJIT_I32_OP)+/* Flags: - (may destroy flags)+ Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.+ The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.+ Note: if SLJIT_R1 is 0, the behaviour is undefined.+ Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),+ the behaviour is undefined. */+#define SLJIT_DIV_SW (SLJIT_OP0_BASE + 7)+#define SLJIT_DIV_S32 (SLJIT_DIV_SW | SLJIT_I32_OP)+/* Flags: - (does not modify flags)+ ENDBR32 instruction for x86-32 and ENDBR64 instruction for x86-64+ when Intel Control-flow Enforcement Technology (CET) is enabled.+ No instruction for other architectures. */+#define SLJIT_ENDBR (SLJIT_OP0_BASE + 8)+/* Flags: - (may destroy flags)+ Skip stack frames before return. */+#define SLJIT_SKIP_FRAMES_BEFORE_RETURN (SLJIT_OP0_BASE + 9)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op);++/* Starting index of opcodes for sljit_emit_op1. */+#define SLJIT_OP1_BASE 32++/* The MOV instruction transfers data from source to destination.++ MOV instruction suffixes:++ U8 - unsigned 8 bit data transfer+ S8 - signed 8 bit data transfer+ U16 - unsigned 16 bit data transfer+ S16 - signed 16 bit data transfer+ U32 - unsigned int (32 bit) data transfer+ S32 - signed int (32 bit) data transfer+ P - pointer (sljit_p) data transfer+*/++/* Flags: - (does not modify flags) */+#define SLJIT_MOV (SLJIT_OP1_BASE + 0)+/* Flags: - (does not modify flags) */+#define SLJIT_MOV_U8 (SLJIT_OP1_BASE + 1)+#define SLJIT_MOV32_U8 (SLJIT_MOV_U8 | SLJIT_I32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_MOV_S8 (SLJIT_OP1_BASE + 2)+#define SLJIT_MOV32_S8 (SLJIT_MOV_S8 | SLJIT_I32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_MOV_U16 (SLJIT_OP1_BASE + 3)+#define SLJIT_MOV32_U16 (SLJIT_MOV_U16 | SLJIT_I32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_MOV_S16 (SLJIT_OP1_BASE + 4)+#define SLJIT_MOV32_S16 (SLJIT_MOV_S16 | SLJIT_I32_OP)+/* Flags: - (does not modify flags)+ Note: no SLJIT_MOV32_U32 form, since it is the same as SLJIT_MOV32 */+#define SLJIT_MOV_U32 (SLJIT_OP1_BASE + 5)+/* Flags: - (does not modify flags)+ Note: no SLJIT_MOV32_S32 form, since it is the same as SLJIT_MOV32 */+#define SLJIT_MOV_S32 (SLJIT_OP1_BASE + 6)+/* Flags: - (does not modify flags) */+#define SLJIT_MOV32 (SLJIT_MOV_S32 | SLJIT_I32_OP)+/* Flags: - (does not modify flags)+ Note: load a pointer sized data, useful on x32 (a 32 bit mode on x86-64+ where all x64 features are available, e.g. 16 register) or similar+ compiling modes */+#define SLJIT_MOV_P (SLJIT_OP1_BASE + 7)+/* Flags: Z+ Note: immediate source argument is not supported */+#define SLJIT_NOT (SLJIT_OP1_BASE + 8)+#define SLJIT_NOT32 (SLJIT_NOT | SLJIT_I32_OP)+/* Flags: Z | OVERFLOW+ Note: immediate source argument is not supported */+#define SLJIT_NEG (SLJIT_OP1_BASE + 9)+#define SLJIT_NEG32 (SLJIT_NEG | SLJIT_I32_OP)+/* Count leading zeroes+ Flags: - (may destroy flags)+ Note: immediate source argument is not supported */+#define SLJIT_CLZ (SLJIT_OP1_BASE + 10)+#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_I32_OP)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw);++/* Starting index of opcodes for sljit_emit_op2. */+#define SLJIT_OP2_BASE 96++/* Flags: Z | OVERFLOW | CARRY */+#define SLJIT_ADD (SLJIT_OP2_BASE + 0)+#define SLJIT_ADD32 (SLJIT_ADD | SLJIT_I32_OP)+/* Flags: CARRY */+#define SLJIT_ADDC (SLJIT_OP2_BASE + 1)+#define SLJIT_ADDC32 (SLJIT_ADDC | SLJIT_I32_OP)+/* Flags: Z | LESS | GREATER_EQUAL | GREATER | LESS_EQUAL+ SIG_LESS | SIG_GREATER_EQUAL | SIG_GREATER+ SIG_LESS_EQUAL | CARRY */+#define SLJIT_SUB (SLJIT_OP2_BASE + 2)+#define SLJIT_SUB32 (SLJIT_SUB | SLJIT_I32_OP)+/* Flags: CARRY */+#define SLJIT_SUBC (SLJIT_OP2_BASE + 3)+#define SLJIT_SUBC32 (SLJIT_SUBC | SLJIT_I32_OP)+/* Note: integer mul+ Flags: MUL_OVERFLOW */+#define SLJIT_MUL (SLJIT_OP2_BASE + 4)+#define SLJIT_MUL32 (SLJIT_MUL | SLJIT_I32_OP)+/* Flags: Z */+#define SLJIT_AND (SLJIT_OP2_BASE + 5)+#define SLJIT_AND32 (SLJIT_AND | SLJIT_I32_OP)+/* Flags: Z */+#define SLJIT_OR (SLJIT_OP2_BASE + 6)+#define SLJIT_OR32 (SLJIT_OR | SLJIT_I32_OP)+/* Flags: Z */+#define SLJIT_XOR (SLJIT_OP2_BASE + 7)+#define SLJIT_XOR32 (SLJIT_XOR | SLJIT_I32_OP)+/* Flags: Z+ Let bit_length be the length of the shift operation: 32 or 64.+ If src2 is immediate, src2w is masked by (bit_length - 1).+ Otherwise, if the content of src2 is outside the range from 0+ to bit_length - 1, the result is undefined. */+#define SLJIT_SHL (SLJIT_OP2_BASE + 8)+#define SLJIT_SHL32 (SLJIT_SHL | SLJIT_I32_OP)+/* Flags: Z+ Let bit_length be the length of the shift operation: 32 or 64.+ If src2 is immediate, src2w is masked by (bit_length - 1).+ Otherwise, if the content of src2 is outside the range from 0+ to bit_length - 1, the result is undefined. */+#define SLJIT_LSHR (SLJIT_OP2_BASE + 9)+#define SLJIT_LSHR32 (SLJIT_LSHR | SLJIT_I32_OP)+/* Flags: Z+ Let bit_length be the length of the shift operation: 32 or 64.+ If src2 is immediate, src2w is masked by (bit_length - 1).+ Otherwise, if the content of src2 is outside the range from 0+ to bit_length - 1, the result is undefined. */+#define SLJIT_ASHR (SLJIT_OP2_BASE + 10)+#define SLJIT_ASHR32 (SLJIT_ASHR | SLJIT_I32_OP)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++/* Starting index of opcodes for sljit_emit_op2. */+#define SLJIT_OP_SRC_BASE 128++/* Note: src cannot be an immedate value+ Flags: - (does not modify flags) */+#define SLJIT_FAST_RETURN (SLJIT_OP_SRC_BASE + 0)+/* Skip stack frames before fast return.+ Note: src cannot be an immedate value+ Flags: may destroy flags. */+#define SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN (SLJIT_OP_SRC_BASE + 1)+/* Prefetch value into the level 1 data cache+ Note: if the target CPU does not support data prefetch,+ no instructions are emitted.+ Note: this instruction never fails, even if the memory address is invalid.+ Flags: - (does not modify flags) */+#define SLJIT_PREFETCH_L1 (SLJIT_OP_SRC_BASE + 2)+/* Prefetch value into the level 2 data cache+ Note: same as SLJIT_PREFETCH_L1 if the target CPU+ does not support this instruction form.+ Note: this instruction never fails, even if the memory address is invalid.+ Flags: - (does not modify flags) */+#define SLJIT_PREFETCH_L2 (SLJIT_OP_SRC_BASE + 3)+/* Prefetch value into the level 3 data cache+ Note: same as SLJIT_PREFETCH_L2 if the target CPU+ does not support this instruction form.+ Note: this instruction never fails, even if the memory address is invalid.+ Flags: - (does not modify flags) */+#define SLJIT_PREFETCH_L3 (SLJIT_OP_SRC_BASE + 4)+/* Prefetch a value which is only used once (and can be discarded afterwards)+ Note: same as SLJIT_PREFETCH_L1 if the target CPU+ does not support this instruction form.+ Note: this instruction never fails, even if the memory address is invalid.+ Flags: - (does not modify flags) */+#define SLJIT_PREFETCH_ONCE (SLJIT_OP_SRC_BASE + 5)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw);++/* Starting index of opcodes for sljit_emit_fop1. */+#define SLJIT_FOP1_BASE 160++/* Flags: - (does not modify flags) */+#define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0)+#define SLJIT_MOV_F32 (SLJIT_MOV_F64 | SLJIT_F32_OP)+/* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE]+ SRC/DST TYPE can be: D - double, S - single, W - signed word, I - signed int+ Rounding mode when the destination is W or I: round towards zero. */+/* Flags: - (does not modify flags) */+#define SLJIT_CONV_F64_FROM_F32 (SLJIT_FOP1_BASE + 1)+#define SLJIT_CONV_F32_FROM_F64 (SLJIT_CONV_F64_FROM_F32 | SLJIT_F32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_CONV_SW_FROM_F64 (SLJIT_FOP1_BASE + 2)+#define SLJIT_CONV_SW_FROM_F32 (SLJIT_CONV_SW_FROM_F64 | SLJIT_F32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_CONV_S32_FROM_F64 (SLJIT_FOP1_BASE + 3)+#define SLJIT_CONV_S32_FROM_F32 (SLJIT_CONV_S32_FROM_F64 | SLJIT_F32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_CONV_F64_FROM_SW (SLJIT_FOP1_BASE + 4)+#define SLJIT_CONV_F32_FROM_SW (SLJIT_CONV_F64_FROM_SW | SLJIT_F32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_CONV_F64_FROM_S32 (SLJIT_FOP1_BASE + 5)+#define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_F32_OP)+/* Note: dst is the left and src is the right operand for SLJIT_CMPD.+ Flags: EQUAL_F | LESS_F | GREATER_EQUAL_F | GREATER_F | LESS_EQUAL_F */+#define SLJIT_CMP_F64 (SLJIT_FOP1_BASE + 6)+#define SLJIT_CMP_F32 (SLJIT_CMP_F64 | SLJIT_F32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_NEG_F64 (SLJIT_FOP1_BASE + 7)+#define SLJIT_NEG_F32 (SLJIT_NEG_F64 | SLJIT_F32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_ABS_F64 (SLJIT_FOP1_BASE + 8)+#define SLJIT_ABS_F32 (SLJIT_ABS_F64 | SLJIT_F32_OP)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw);++/* Starting index of opcodes for sljit_emit_fop2. */+#define SLJIT_FOP2_BASE 192++/* Flags: - (does not modify flags) */+#define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0)+#define SLJIT_ADD_F32 (SLJIT_ADD_F64 | SLJIT_F32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_SUB_F64 (SLJIT_FOP2_BASE + 1)+#define SLJIT_SUB_F32 (SLJIT_SUB_F64 | SLJIT_F32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_MUL_F64 (SLJIT_FOP2_BASE + 2)+#define SLJIT_MUL_F32 (SLJIT_MUL_F64 | SLJIT_F32_OP)+/* Flags: - (does not modify flags) */+#define SLJIT_DIV_F64 (SLJIT_FOP2_BASE + 3)+#define SLJIT_DIV_F32 (SLJIT_DIV_F64 | SLJIT_F32_OP)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++/* Label and jump instructions. */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler);++/* Invert (negate) conditional type: xor (^) with 0x1 */++/* Integer comparison types. */+#define SLJIT_EQUAL 0+#define SLJIT_EQUAL32 (SLJIT_EQUAL | SLJIT_I32_OP)+#define SLJIT_ZERO 0+#define SLJIT_ZERO32 (SLJIT_ZERO | SLJIT_I32_OP)+#define SLJIT_NOT_EQUAL 1+#define SLJIT_NOT_EQUAL32 (SLJIT_NOT_EQUAL | SLJIT_I32_OP)+#define SLJIT_NOT_ZERO 1+#define SLJIT_NOT_ZERO32 (SLJIT_NOT_ZERO | SLJIT_I32_OP)++#define SLJIT_LESS 2+#define SLJIT_LESS32 (SLJIT_LESS | SLJIT_I32_OP)+#define SLJIT_SET_LESS SLJIT_SET(SLJIT_LESS)+#define SLJIT_GREATER_EQUAL 3+#define SLJIT_GREATER_EQUAL32 (SLJIT_GREATER_EQUAL | SLJIT_I32_OP)+#define SLJIT_SET_GREATER_EQUAL SLJIT_SET(SLJIT_GREATER_EQUAL)+#define SLJIT_GREATER 4+#define SLJIT_GREATER32 (SLJIT_GREATER | SLJIT_I32_OP)+#define SLJIT_SET_GREATER SLJIT_SET(SLJIT_GREATER)+#define SLJIT_LESS_EQUAL 5+#define SLJIT_LESS_EQUAL32 (SLJIT_LESS_EQUAL | SLJIT_I32_OP)+#define SLJIT_SET_LESS_EQUAL SLJIT_SET(SLJIT_LESS_EQUAL)+#define SLJIT_SIG_LESS 6+#define SLJIT_SIG_LESS32 (SLJIT_SIG_LESS | SLJIT_I32_OP)+#define SLJIT_SET_SIG_LESS SLJIT_SET(SLJIT_SIG_LESS)+#define SLJIT_SIG_GREATER_EQUAL 7+#define SLJIT_SIG_GREATER_EQUAL32 (SLJIT_SIG_GREATER_EQUAL | SLJIT_I32_OP)+#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SIG_GREATER_EQUAL)+#define SLJIT_SIG_GREATER 8+#define SLJIT_SIG_GREATER32 (SLJIT_SIG_GREATER | SLJIT_I32_OP)+#define SLJIT_SET_SIG_GREATER SLJIT_SET(SLJIT_SIG_GREATER)+#define SLJIT_SIG_LESS_EQUAL 9+#define SLJIT_SIG_LESS_EQUAL32 (SLJIT_SIG_LESS_EQUAL | SLJIT_I32_OP)+#define SLJIT_SET_SIG_LESS_EQUAL SLJIT_SET(SLJIT_SIG_LESS_EQUAL)++#define SLJIT_OVERFLOW 10+#define SLJIT_OVERFLOW32 (SLJIT_OVERFLOW | SLJIT_I32_OP)+#define SLJIT_SET_OVERFLOW SLJIT_SET(SLJIT_OVERFLOW)+#define SLJIT_NOT_OVERFLOW 11+#define SLJIT_NOT_OVERFLOW32 (SLJIT_NOT_OVERFLOW | SLJIT_I32_OP)++#define SLJIT_MUL_OVERFLOW 12+#define SLJIT_MUL_OVERFLOW32 (SLJIT_MUL_OVERFLOW | SLJIT_I32_OP)+#define SLJIT_SET_MUL_OVERFLOW SLJIT_SET(SLJIT_MUL_OVERFLOW)+#define SLJIT_MUL_NOT_OVERFLOW 13+#define SLJIT_MUL_NOT_OVERFLOW32 (SLJIT_MUL_NOT_OVERFLOW | SLJIT_I32_OP)++/* There is no SLJIT_CARRY or SLJIT_NOT_CARRY. */+#define SLJIT_SET_CARRY SLJIT_SET(14)++/* Floating point comparison types. */+#define SLJIT_EQUAL_F64 16+#define SLJIT_EQUAL_F32 (SLJIT_EQUAL_F64 | SLJIT_F32_OP)+#define SLJIT_SET_EQUAL_F SLJIT_SET(SLJIT_EQUAL_F64)+#define SLJIT_NOT_EQUAL_F64 17+#define SLJIT_NOT_EQUAL_F32 (SLJIT_NOT_EQUAL_F64 | SLJIT_F32_OP)+#define SLJIT_SET_NOT_EQUAL_F SLJIT_SET(SLJIT_NOT_EQUAL_F64)+#define SLJIT_LESS_F64 18+#define SLJIT_LESS_F32 (SLJIT_LESS_F64 | SLJIT_F32_OP)+#define SLJIT_SET_LESS_F SLJIT_SET(SLJIT_LESS_F64)+#define SLJIT_GREATER_EQUAL_F64 19+#define SLJIT_GREATER_EQUAL_F32 (SLJIT_GREATER_EQUAL_F64 | SLJIT_F32_OP)+#define SLJIT_SET_GREATER_EQUAL_F SLJIT_SET(SLJIT_GREATER_EQUAL_F64)+#define SLJIT_GREATER_F64 20+#define SLJIT_GREATER_F32 (SLJIT_GREATER_F64 | SLJIT_F32_OP)+#define SLJIT_SET_GREATER_F SLJIT_SET(SLJIT_GREATER_F64)+#define SLJIT_LESS_EQUAL_F64 21+#define SLJIT_LESS_EQUAL_F32 (SLJIT_LESS_EQUAL_F64 | SLJIT_F32_OP)+#define SLJIT_SET_LESS_EQUAL_F SLJIT_SET(SLJIT_LESS_EQUAL_F64)+#define SLJIT_UNORDERED_F64 22+#define SLJIT_UNORDERED_F32 (SLJIT_UNORDERED_F64 | SLJIT_F32_OP)+#define SLJIT_SET_UNORDERED_F SLJIT_SET(SLJIT_UNORDERED_F64)+#define SLJIT_ORDERED_F64 23+#define SLJIT_ORDERED_F32 (SLJIT_ORDERED_F64 | SLJIT_F32_OP)+#define SLJIT_SET_ORDERED_F SLJIT_SET(SLJIT_ORDERED_F64)++/* Unconditional jump types. */+#define SLJIT_JUMP 24+ /* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */+#define SLJIT_FAST_CALL 25+ /* Called function must be declared with the SLJIT_FUNC attribute. */+#define SLJIT_CALL 26+ /* Called function must be declared with cdecl attribute.+ This is the default attribute for C functions. */+#define SLJIT_CALL_CDECL 27++/* The target can be changed during runtime (see: sljit_set_jump_addr). */+#define SLJIT_REWRITABLE_JUMP 0x1000++/* Emit a jump instruction. The destination is not set, only the type of the jump.+ type must be between SLJIT_EQUAL and SLJIT_FAST_CALL+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP++ Flags: does not modify flags. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type);++/* Emit a C compiler (ABI) compatible function call.+ type must be SLJIT_CALL or SLJIT_CALL_CDECL+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP+ arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros++ Flags: destroy all flags. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types);++/* Basic arithmetic comparison. In most architectures it is implemented as+ an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting+ appropriate flags) followed by a sljit_emit_jump. However some+ architectures (i.e: ARM64 or MIPS) may employ special optimizations here.+ It is suggested to use this comparison form when appropriate.+ type must be between SLJIT_EQUAL and SLJIT_I_SIG_LESS_EQUAL+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP++ Flags: may destroy flags. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++/* Basic floating point comparison. In most architectures it is implemented as+ an SLJIT_FCMP operation (setting appropriate flags) followed by a+ sljit_emit_jump. However some architectures (i.e: MIPS) may employ+ special optimizations here. It is suggested to use this comparison form+ when appropriate.+ type must be between SLJIT_EQUAL_F64 and SLJIT_ORDERED_F32+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP+ Flags: destroy flags.+ Note: if either operand is NaN, the behaviour is undefined for+ types up to SLJIT_S_LESS_EQUAL. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++/* Set the destination of the jump to this label. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label);+/* Set the destination address of the jump to this label. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target);++/* Emit an indirect jump or fast call.+ Direct form: set src to SLJIT_IMM() and srcw to the address+ Indirect form: any other valid addressing mode+ type must be between SLJIT_JUMP and SLJIT_FAST_CALL++ Flags: does not modify flags. */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw);++/* Emit a C compiler (ABI) compatible function call.+ Direct form: set src to SLJIT_IMM() and srcw to the address+ Indirect form: any other valid addressing mode+ type must be SLJIT_CALL or SLJIT_CALL_CDECL+ arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros++ Flags: destroy all flags. */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw);++/* Perform the operation using the conditional flags as the second argument.+ Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_F64. The value+ represented by the type is 1, if the condition represented by the type+ is fulfilled, and 0 otherwise.++ If op == SLJIT_MOV, SLJIT_MOV32:+ Set dst to the value represented by the type (0 or 1).+ Flags: - (does not modify flags)+ If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR+ Performs the binary operation using dst as the first, and the value+ represented by type as the second argument. Result is written into dst.+ Flags: Z (may destroy flags) */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 type);++/* Emit a conditional mov instruction which moves source to destination,+ if the condition is satisfied. Unlike other arithmetic operations this+ instruction does not support memory access.++ type must be between SLJIT_EQUAL and SLJIT_ORDERED_F64+ dst_reg must be a valid register and it can be combined+ with SLJIT_I32_OP to perform a 32 bit arithmetic operation+ src must be register or immediate (SLJIT_IMM)++ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw);++/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */++/* When SLJIT_MEM_SUPP is passed, no instructions are emitted.+ Instead the function returns with SLJIT_SUCCESS if the instruction+ form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag+ allows runtime checking of available instruction forms. */+#define SLJIT_MEM_SUPP 0x0200+/* Memory load operation. This is the default. */+#define SLJIT_MEM_LOAD 0x0000+/* Memory store operation. */+#define SLJIT_MEM_STORE 0x0400+/* Base register is updated before the memory access. */+#define SLJIT_MEM_PRE 0x0800+/* Base register is updated after the memory access. */+#define SLJIT_MEM_POST 0x1000++/* Emit a single memory load or store with update instruction. When the+ requested instruction form is not supported by the CPU, it returns+ with SLJIT_ERR_UNSUPPORTED instead of emulating the instruction. This+ allows specializing tight loops based on the supported instruction+ forms (see SLJIT_MEM_SUPP flag).++ type must be between SLJIT_MOV and SLJIT_MOV_P and can be+ combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE+ or SLJIT_MEM_POST must be specified.+ reg is the source or destination register, and must be+ different from the base register of the mem operand+ mem must be a SLJIT_MEM1() or SLJIT_MEM2() operand++ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw);++/* Same as sljit_emit_mem except the followings:++ type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be+ combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE+ or SLJIT_MEM_POST must be specified.+ freg is the source or destination floating point register */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw);++/* Copies the base address of SLJIT_SP + offset to dst. The offset can be+ anything to negate the effect of relative addressing. For example if an+ array of sljit_sw values is stored on the stack from offset 0x40, and R0+ contains the offset of an array item plus 0x120, this item can be+ overwritten by two SLJIT instructions:++ sljit_get_local_base(compiler, SLJIT_R1, 0, 0x40 - 0x120);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_IMM, 0x5);++ Flags: - (may destroy flags) */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset);++/* Store a value that can be changed runtime (see: sljit_get_const_addr / sljit_set_const)+ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value);++/* Store the value of a label (see: sljit_set_put_label)+ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);++/* Set the value stored by put_label to this label. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label);++/* After the code generation the address for label, jump and const instructions+ are computed. Since these structures are freed by sljit_free_compiler, the+ addresses must be preserved by the user program elsewere. */+static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->addr; }+static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; }+static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; }++/* Only the address and executable offset are required to perform dynamic+ code modifications. See sljit_get_executable_offset function. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset);+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset);++/* --------------------------------------------------------------------- */+/* Miscellaneous utility functions */+/* --------------------------------------------------------------------- */++#define SLJIT_MAJOR_VERSION 0+#define SLJIT_MINOR_VERSION 94++/* Get the human readable name of the platform. Can be useful on platforms+ like ARM, where ARM and Thumb2 functions can be mixed, and+ it is useful to know the type of the code generator. */+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void);++/* Portable helper function to get an offset of a member. */+#define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10)++#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)++/* The sljit_stack structure and its manipulation functions provides+ an implementation for a top-down stack. The stack top is stored+ in the end field of the sljit_stack structure and the stack goes+ down to the min_start field, so the memory region reserved for+ this stack is between min_start (inclusive) and end (exclusive)+ fields. However the application can only use the region between+ start (inclusive) and end (exclusive) fields. The sljit_stack_resize+ function can be used to extend this region up to min_start.++ This feature uses the "address space reserve" feature of modern+ operating systems. Instead of allocating a large memory block+ applications can allocate a small memory region and extend it+ later without moving the content of the memory area. Therefore+ after a successful resize by sljit_stack_resize all pointers into+ this region are still valid.++ Note:+ this structure may not be supported by all operating systems.+ end and max_limit fields are aligned to PAGE_SIZE bytes (usually+ 4 Kbyte or more).+ stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more. */++struct sljit_stack {+ /* User data, anything can be stored here.+ Initialized to the same value as the end field. */+ sljit_u8 *top;+/* These members are read only. */+ /* End address of the stack */+ sljit_u8 *end;+ /* Current start address of the stack. */+ sljit_u8 *start;+ /* Lowest start address of the stack. */+ sljit_u8 *min_start;+};++/* Allocates a new stack. Returns NULL if unsuccessful.+ Note: see sljit_create_compiler for the explanation of allocator_data. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data);+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data);++/* Can be used to increase (extend) or decrease (shrink) the stack+ memory area. Returns with new_start if successful and NULL otherwise.+ It always fails if new_start is less than min_start or greater or equal+ than end fields. The fields of the stack are not changed if the returned+ value is NULL (the current memory content is never lost). */+SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start);++#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */++#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)++/* Get the entry address of a given function. */+#define SLJIT_FUNC_OFFSET(func_name) ((sljit_sw)func_name)++#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */++/* All JIT related code should be placed in the same context (library, binary, etc.). */++#define SLJIT_FUNC_OFFSET(func_name) (*(sljit_sw*)(void*)func_name)++/* For powerpc64, the function pointers point to a context descriptor. */+struct sljit_function_context {+ sljit_sw addr;+ sljit_sw r2;+ sljit_sw r11;+};++/* Fill the context arguments using the addr and the function.+ If func_ptr is NULL, it will not be set to the address of context+ If addr is NULL, the function address also comes from the func pointer. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func);++#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */++#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)+/* Free unused executable memory. The allocator keeps some free memory+ around to reduce the number of OS executable memory allocations.+ This improves performance since these calls are costly. However+ it is sometimes desired to free all unused memory regions, e.g.+ before the application terminates. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);+#endif++/* --------------------------------------------------------------------- */+/* CPU specific functions */+/* --------------------------------------------------------------------- */++/* The following function is a helper function for sljit_emit_op_custom.+ It returns with the real machine register index ( >=0 ) of any SLJIT_R,+ SLJIT_S and SLJIT_SP registers.++ Note: it returns with -1 for virtual registers (only on x86-32). */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg);++/* The following function is a helper function for sljit_emit_op_custom.+ It returns with the real machine register index of any SLJIT_FLOAT register.++ Note: the index is always an even number on ARM (except ARM-64), MIPS, and SPARC. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg);++/* Any instruction can be inserted into the instruction stream by+ sljit_emit_op_custom. It has a similar purpose as inline assembly.+ The size parameter must match to the instruction size of the target+ architecture:++ x86: 0 < size <= 15. The instruction argument can be byte aligned.+ Thumb2: if size == 2, the instruction argument must be 2 byte aligned.+ if size == 4, the instruction argument must be 4 byte aligned.+ Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size);++/* Define the currently available CPU status flags. It is usually used after an+ sljit_emit_op_custom call to define which flags are set. */++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler,+ sljit_s32 current_flags);++#ifdef __cplusplus+} /* extern "C" */+#endif++#endif /* SLJIT_LIR_H_ */
+ src/c/pcre2/src/sljit/sljitNativeARM_32.c view
@@ -0,0 +1,2824 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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 __SOFTFP__+#define ARM_ABI_INFO " ABI:softfp"+#else+#define ARM_ABI_INFO " ABI:hardfp"+#endif++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ return "ARMv7" SLJIT_CPUINFO ARM_ABI_INFO;+#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ return "ARMv5" SLJIT_CPUINFO ARM_ABI_INFO;+#else+#error "Internal error: Unknown ARM architecture"+#endif+}++/* Last register + 1. */+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)+#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4)++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)++/* In ARM instruction words.+ Cache lines are usually 32 byte aligned. */+#define CONST_POOL_ALIGNMENT 8+#define CONST_POOL_EMPTY 0xffffffff++#define ALIGN_INSTRUCTION(ptr) \+ (sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1))+#define MAX_DIFFERENCE(max_diff) \+ (((max_diff) / (sljit_s32)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))++/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {+ 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15+};++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {+ 0, 0, 1, 2, 3, 4, 5, 6, 7+};++#define RM(rm) (reg_map[rm])+#define RD(rd) (reg_map[rd] << 12)+#define RN(rn) (reg_map[rn] << 16)++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++/* The instruction includes the AL condition.+ INST_NAME - CONDITIONAL remove this flag. */+#define COND_MASK 0xf0000000+#define CONDITIONAL 0xe0000000+#define PUSH_POOL 0xff000000++#define ADC 0xe0a00000+#define ADD 0xe0800000+#define AND 0xe0000000+#define B 0xea000000+#define BIC 0xe1c00000+#define BL 0xeb000000+#define BLX 0xe12fff30+#define BX 0xe12fff10+#define CLZ 0xe16f0f10+#define CMN 0xe1600000+#define CMP 0xe1400000+#define BKPT 0xe1200070+#define EOR 0xe0200000+#define MOV 0xe1a00000+#define MUL 0xe0000090+#define MVN 0xe1e00000+#define NOP 0xe1a00000+#define ORR 0xe1800000+#define PUSH 0xe92d0000+#define POP 0xe8bd0000+#define RSB 0xe0600000+#define RSC 0xe0e00000+#define SBC 0xe0c00000+#define SMULL 0xe0c00090+#define SUB 0xe0400000+#define UMULL 0xe0800090+#define VABS_F32 0xeeb00ac0+#define VADD_F32 0xee300a00+#define VCMP_F32 0xeeb40a40+#define VCVT_F32_S32 0xeeb80ac0+#define VCVT_F64_F32 0xeeb70ac0+#define VCVT_S32_F32 0xeebd0ac0+#define VDIV_F32 0xee800a00+#define VMOV_F32 0xeeb00a40+#define VMOV 0xee000a10+#define VMOV2 0xec400a10+#define VMRS 0xeef1fa10+#define VMUL_F32 0xee200a00+#define VNEG_F32 0xeeb10a40+#define VSTR_F32 0xed000a00+#define VSUB_F32 0xee300a40++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+/* Arm v7 specific instructions. */+#define MOVW 0xe3000000+#define MOVT 0xe3400000+#define SXTB 0xe6af0070+#define SXTH 0xe6bf0070+#define UXTB 0xe6ef0070+#define UXTH 0xe6ff0070+#endif++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)++static sljit_s32 push_cpool(struct sljit_compiler *compiler)+{+ /* Pushing the constant pool into the instruction stream. */+ sljit_uw* inst;+ sljit_uw* cpool_ptr;+ sljit_uw* cpool_end;+ sljit_s32 i;++ /* The label could point the address after the constant pool. */+ if (compiler->last_label && compiler->last_label->size == compiler->size)+ compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1;++ SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE);+ inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));+ FAIL_IF(!inst);+ compiler->size++;+ *inst = 0xff000000 | compiler->cpool_fill;++ for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) {+ inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));+ FAIL_IF(!inst);+ compiler->size++;+ *inst = 0;+ }++ cpool_ptr = compiler->cpool;+ cpool_end = cpool_ptr + compiler->cpool_fill;+ while (cpool_ptr < cpool_end) {+ inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));+ FAIL_IF(!inst);+ compiler->size++;+ *inst = *cpool_ptr++;+ }+ compiler->cpool_diff = CONST_POOL_EMPTY;+ compiler->cpool_fill = 0;+ return SLJIT_SUCCESS;+}++static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst)+{+ sljit_uw* ptr;++ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))+ FAIL_IF(push_cpool(compiler));++ ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));+ FAIL_IF(!ptr);+ compiler->size++;+ *ptr = inst;+ return SLJIT_SUCCESS;+}++static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)+{+ sljit_uw* ptr;+ sljit_uw cpool_index = CPOOL_SIZE;+ sljit_uw* cpool_ptr;+ sljit_uw* cpool_end;+ sljit_u8* cpool_unique_ptr;++ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))+ FAIL_IF(push_cpool(compiler));+ else if (compiler->cpool_fill > 0) {+ cpool_ptr = compiler->cpool;+ cpool_end = cpool_ptr + compiler->cpool_fill;+ cpool_unique_ptr = compiler->cpool_unique;+ do {+ if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) {+ cpool_index = cpool_ptr - compiler->cpool;+ break;+ }+ cpool_ptr++;+ cpool_unique_ptr++;+ } while (cpool_ptr < cpool_end);+ }++ if (cpool_index == CPOOL_SIZE) {+ /* Must allocate a new entry in the literal pool. */+ if (compiler->cpool_fill < CPOOL_SIZE) {+ cpool_index = compiler->cpool_fill;+ compiler->cpool_fill++;+ }+ else {+ FAIL_IF(push_cpool(compiler));+ cpool_index = 0;+ compiler->cpool_fill = 1;+ }+ }++ SLJIT_ASSERT((inst & 0xfff) == 0);+ ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));+ FAIL_IF(!ptr);+ compiler->size++;+ *ptr = inst | cpool_index;++ compiler->cpool[cpool_index] = literal;+ compiler->cpool_unique[cpool_index] = 0;+ if (compiler->cpool_diff == CONST_POOL_EMPTY)+ compiler->cpool_diff = compiler->size;+ return SLJIT_SUCCESS;+}++static sljit_s32 push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)+{+ sljit_uw* ptr;+ if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE))+ FAIL_IF(push_cpool(compiler));++ SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0);+ ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));+ FAIL_IF(!ptr);+ compiler->size++;+ *ptr = inst | compiler->cpool_fill;++ compiler->cpool[compiler->cpool_fill] = literal;+ compiler->cpool_unique[compiler->cpool_fill] = 1;+ compiler->cpool_fill++;+ if (compiler->cpool_diff == CONST_POOL_EMPTY)+ compiler->cpool_diff = compiler->size;+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 prepare_blx(struct sljit_compiler *compiler)+{+ /* Place for at least two instruction (doesn't matter whether the first has a literal). */+ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088)))+ return push_cpool(compiler);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_blx(struct sljit_compiler *compiler)+{+ /* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */+ SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092));+ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);++ return push_inst(compiler, BLX | RM(TMP_REG1));+}++static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size)+{+ sljit_uw diff;+ sljit_uw ind;+ sljit_uw counter = 0;+ sljit_uw* clear_const_pool = const_pool;+ sljit_uw* clear_const_pool_end = const_pool + cpool_size;++ SLJIT_ASSERT(const_pool - code_ptr <= CONST_POOL_ALIGNMENT);+ /* Set unused flag for all literals in the constant pool.+ I.e.: unused literals can belong to branches, which can be encoded as B or BL.+ We can "compress" the constant pool by discarding these literals. */+ while (clear_const_pool < clear_const_pool_end)+ *clear_const_pool++ = (sljit_uw)(-1);++ while (last_pc_patch < code_ptr) {+ /* Data transfer instruction with Rn == r15. */+ if ((*last_pc_patch & 0x0c0f0000) == 0x040f0000) {+ diff = const_pool - last_pc_patch;+ ind = (*last_pc_patch) & 0xfff;++ /* Must be a load instruction with immediate offset. */+ SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20)));+ if ((sljit_s32)const_pool[ind] < 0) {+ const_pool[ind] = counter;+ ind = counter;+ counter++;+ }+ else+ ind = const_pool[ind];++ SLJIT_ASSERT(diff >= 1);+ if (diff >= 2 || ind > 0) {+ diff = (diff + ind - 2) << 2;+ SLJIT_ASSERT(diff <= 0xfff);+ *last_pc_patch = (*last_pc_patch & ~0xfff) | diff;+ }+ else+ *last_pc_patch = (*last_pc_patch & ~(0xfff | (1 << 23))) | 0x004;+ }+ last_pc_patch++;+ }+ return counter;+}++/* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */+struct future_patch {+ struct future_patch* next;+ sljit_s32 index;+ sljit_s32 value;+};++static sljit_s32 resolve_const_pool_index(struct sljit_compiler *compiler, struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr)+{+ sljit_s32 value;+ struct future_patch *curr_patch, *prev_patch;++ SLJIT_UNUSED_ARG(compiler);++ /* Using the values generated by patch_pc_relative_loads. */+ if (!*first_patch)+ value = (sljit_s32)cpool_start_address[cpool_current_index];+ else {+ curr_patch = *first_patch;+ prev_patch = NULL;+ while (1) {+ if (!curr_patch) {+ value = (sljit_s32)cpool_start_address[cpool_current_index];+ break;+ }+ if ((sljit_uw)curr_patch->index == cpool_current_index) {+ value = curr_patch->value;+ if (prev_patch)+ prev_patch->next = curr_patch->next;+ else+ *first_patch = curr_patch->next;+ SLJIT_FREE(curr_patch, compiler->allocator_data);+ break;+ }+ prev_patch = curr_patch;+ curr_patch = curr_patch->next;+ }+ }++ if (value >= 0) {+ if ((sljit_uw)value > cpool_current_index) {+ curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch), compiler->allocator_data);+ if (!curr_patch) {+ while (*first_patch) {+ curr_patch = *first_patch;+ *first_patch = (*first_patch)->next;+ SLJIT_FREE(curr_patch, compiler->allocator_data);+ }+ return SLJIT_ERR_ALLOC_FAILED;+ }+ curr_patch->next = *first_patch;+ curr_patch->index = value;+ curr_patch->value = cpool_start_address[value];+ *first_patch = curr_patch;+ }+ cpool_start_address[value] = *buf_ptr;+ }+ return SLJIT_SUCCESS;+}++#else++static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst)+{+ sljit_uw* ptr;++ ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));+ FAIL_IF(!ptr);+ compiler->size++;+ *ptr = inst;+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_imm(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)+{+ FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));+ return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));+}++#endif++static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code, sljit_sw executable_offset)+{+ sljit_sw diff;++ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ return 0;++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ if (jump->flags & IS_BL)+ code_ptr--;++ if (jump->flags & JUMP_ADDR)+ diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset);+ else {+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);+ diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2));+ }++ /* Branch to Thumb code has not been optimized yet. */+ if (diff & 0x3)+ return 0;++ if (jump->flags & IS_BL) {+ if (diff <= 0x01ffffff && diff >= -0x02000000) {+ *code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK);+ jump->flags |= PATCH_B;+ return 1;+ }+ }+ else {+ if (diff <= 0x01ffffff && diff >= -0x02000000) {+ *code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK);+ jump->flags |= PATCH_B;+ }+ }+#else+ if (jump->flags & JUMP_ADDR)+ diff = ((sljit_sw)jump->u.target - (sljit_sw)code_ptr - executable_offset);+ else {+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);+ diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)code_ptr);+ }++ /* Branch to Thumb code has not been optimized yet. */+ if (diff & 0x3)+ return 0;++ if (diff <= 0x01ffffff && diff >= -0x02000000) {+ code_ptr -= 2;+ *code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (code_ptr[2] & COND_MASK);+ jump->flags |= PATCH_B;+ return 1;+ }+#endif+ return 0;+}++static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw executable_offset, sljit_uw new_addr, sljit_s32 flush_cache)+{+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ sljit_uw *ptr = (sljit_uw *)jump_ptr;+ sljit_uw *inst = (sljit_uw *)ptr[0];+ sljit_uw mov_pc = ptr[1];+ sljit_s32 bl = (mov_pc & 0x0000f000) != RD(TMP_PC);+ sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2) - executable_offset) >> 2);++ SLJIT_UNUSED_ARG(executable_offset);++ if (diff <= 0x7fffff && diff >= -0x800000) {+ /* Turn to branch. */+ if (!bl) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ }+ inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff);+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+ }+ } else {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ }+ inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff);+ inst[1] = NOP;+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ }+ }+ } else {+ /* Get the position of the constant. */+ if (mov_pc & (1 << 23))+ ptr = inst + ((mov_pc & 0xfff) >> 2) + 2;+ else+ ptr = inst + 1;++ if (*inst != mov_pc) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + (!bl ? 1 : 2), 0);+ }+ inst[0] = mov_pc;+ if (!bl) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+ }+ } else {+ inst[1] = BLX | RM(TMP_REG1);+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ }+ }+ }++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);+ }++ *ptr = new_addr;++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);+ }+ }+#else+ sljit_uw *inst = (sljit_uw*)jump_ptr;++ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ }++ inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff);+ inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff);++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ }+#endif+}++static sljit_uw get_imm(sljit_uw imm);++static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_sw new_constant, sljit_s32 flush_cache)+{+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ sljit_uw *ptr = (sljit_uw*)addr;+ sljit_uw *inst = (sljit_uw*)ptr[0];+ sljit_uw ldr_literal = ptr[1];+ sljit_uw src2;++ SLJIT_UNUSED_ARG(executable_offset);++ src2 = get_imm(new_constant);+ if (src2) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ }++ *inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+ }+ return;+ }++ src2 = get_imm(~new_constant);+ if (src2) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ }++ *inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+ }+ return;+ }++ if (ldr_literal & (1 << 23))+ ptr = inst + ((ldr_literal & 0xfff) >> 2) + 2;+ else+ ptr = inst + 1;++ if (*inst != ldr_literal) {+ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ }++ *inst = ldr_literal;++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+ }+ }++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);+ }++ *ptr = new_constant;++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);+ }+#else+ sljit_uw *inst = (sljit_uw*)addr;++ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ }++ inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff);+ inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff);++ if (flush_cache) {+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ }+#endif+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf;+ sljit_uw *code;+ sljit_uw *code_ptr;+ sljit_uw *buf_ptr;+ sljit_uw *buf_end;+ sljit_uw size;+ sljit_uw word_count;+ sljit_uw next_addr;+ sljit_sw executable_offset;+ sljit_sw addr;+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ sljit_uw cpool_size;+ sljit_uw cpool_skip_alignment;+ sljit_uw cpool_current_index;+ sljit_uw *cpool_start_address;+ sljit_uw *last_pc_patch;+ struct future_patch *first_patch;+#endif++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ struct sljit_put_label *put_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));+ reverse_buf(compiler);++ /* Second code generation pass. */+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ size = compiler->size + (compiler->patches << 1);+ if (compiler->cpool_fill > 0)+ size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1;+#else+ size = compiler->size;+#endif+ code = (sljit_uw*)SLJIT_MALLOC_EXEC(size * sizeof(sljit_uw), compiler->exec_allocator_data);+ PTR_FAIL_WITH_EXEC_IF(code);+ buf = compiler->buf;++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ cpool_size = 0;+ cpool_skip_alignment = 0;+ cpool_current_index = 0;+ cpool_start_address = NULL;+ first_patch = NULL;+ last_pc_patch = code;+#endif++ code_ptr = code;+ word_count = 0;+ next_addr = 1;+ executable_offset = SLJIT_EXEC_OFFSET(code);++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ put_label = compiler->put_labels;++ if (label && label->size == 0) {+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);+ label = label->next;+ }++ do {+ buf_ptr = (sljit_uw*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+ word_count++;+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ if (cpool_size > 0) {+ if (cpool_skip_alignment > 0) {+ buf_ptr++;+ cpool_skip_alignment--;+ }+ else {+ if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {+ SLJIT_FREE_EXEC(code, compiler->exec_allocator_data);+ compiler->error = SLJIT_ERR_ALLOC_FAILED;+ return NULL;+ }+ buf_ptr++;+ if (++cpool_current_index >= cpool_size) {+ SLJIT_ASSERT(!first_patch);+ cpool_size = 0;+ if (label && label->size == word_count) {+ /* Points after the current instruction. */+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = code_ptr - code;+ label = label->next;++ next_addr = compute_next_addr(label, jump, const_, put_label);+ }+ }+ }+ }+ else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {+#endif+ *code_ptr = *buf_ptr++;+ if (next_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);++ /* These structures are ordered by their address. */+ if (jump && jump->addr == word_count) {+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ if (detect_jump_type(jump, code_ptr, code, executable_offset))+ code_ptr--;+ jump->addr = (sljit_uw)code_ptr;+#else+ jump->addr = (sljit_uw)(code_ptr - 2);+ if (detect_jump_type(jump, code_ptr, code, executable_offset))+ code_ptr -= 2;+#endif+ jump = jump->next;+ }+ if (label && label->size == word_count) {+ /* code_ptr can be affected above. */+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);+ label->size = (code_ptr + 1) - code;+ label = label->next;+ }+ if (const_ && const_->addr == word_count) {+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ const_->addr = (sljit_uw)code_ptr;+#else+ const_->addr = (sljit_uw)(code_ptr - 1);+#endif+ const_ = const_->next;+ }+ if (put_label && put_label->addr == word_count) {+ SLJIT_ASSERT(put_label->label);+ put_label->addr = (sljit_uw)code_ptr;+ put_label = put_label->next;+ }+ next_addr = compute_next_addr(label, jump, const_, put_label);+ }+ code_ptr++;+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ }+ else {+ /* Fortunately, no need to shift. */+ cpool_size = *buf_ptr++ & ~PUSH_POOL;+ SLJIT_ASSERT(cpool_size > 0);+ cpool_start_address = ALIGN_INSTRUCTION(code_ptr + 1);+ cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size);+ if (cpool_current_index > 0) {+ /* Unconditional branch. */+ *code_ptr = B | (((cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL);+ code_ptr = cpool_start_address + cpool_current_index;+ }+ cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1;+ cpool_current_index = 0;+ last_pc_patch = code_ptr;+ }+#endif+ } while (buf_ptr < buf_end);+ buf = buf->next;+ } while (buf);++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(!put_label);++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ SLJIT_ASSERT(cpool_size == 0);+ if (compiler->cpool_fill > 0) {+ cpool_start_address = ALIGN_INSTRUCTION(code_ptr);+ cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill);+ if (cpool_current_index > 0)+ code_ptr = cpool_start_address + cpool_current_index;++ buf_ptr = compiler->cpool;+ buf_end = buf_ptr + compiler->cpool_fill;+ cpool_current_index = 0;+ while (buf_ptr < buf_end) {+ if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {+ SLJIT_FREE_EXEC(code, compiler->exec_allocator_data);+ compiler->error = SLJIT_ERR_ALLOC_FAILED;+ return NULL;+ }+ buf_ptr++;+ cpool_current_index++;+ }+ SLJIT_ASSERT(!first_patch);+ }+#endif++ jump = compiler->jumps;+ while (jump) {+ buf_ptr = (sljit_uw *)jump->addr;++ if (jump->flags & PATCH_B) {+ addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);+ if (!(jump->flags & JUMP_ADDR)) {+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);+ SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - addr) >= -0x02000000);+ *buf_ptr |= (((sljit_sw)jump->u.label->addr - addr) >> 2) & 0x00ffffff;+ }+ else {+ SLJIT_ASSERT(((sljit_sw)jump->u.target - addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - addr) >= -0x02000000);+ *buf_ptr |= (((sljit_sw)jump->u.target - addr) >> 2) & 0x00ffffff;+ }+ }+ else if (jump->flags & SLJIT_REWRITABLE_JUMP) {+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ jump->addr = (sljit_uw)code_ptr;+ code_ptr[0] = (sljit_uw)buf_ptr;+ code_ptr[1] = *buf_ptr;+ inline_set_jump_addr((sljit_uw)code_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);+ code_ptr += 2;+#else+ inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);+#endif+ }+ else {+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ if (jump->flags & IS_BL)+ buf_ptr--;+ if (*buf_ptr & (1 << 23))+ buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;+ else+ buf_ptr += 1;+ *buf_ptr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;+#else+ inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);+#endif+ }+ jump = jump->next;+ }++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ const_ = compiler->consts;+ while (const_) {+ buf_ptr = (sljit_uw*)const_->addr;+ const_->addr = (sljit_uw)code_ptr;++ code_ptr[0] = (sljit_uw)buf_ptr;+ code_ptr[1] = *buf_ptr;+ if (*buf_ptr & (1 << 23))+ buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;+ else+ buf_ptr += 1;+ /* Set the value again (can be a simple constant). */+ inline_set_const((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0);+ code_ptr += 2;++ const_ = const_->next;+ }+#endif++ put_label = compiler->put_labels;+ while (put_label) {+ addr = put_label->label->addr;+ buf_ptr = (sljit_uw*)put_label->addr;++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ SLJIT_ASSERT((buf_ptr[0] & 0xffff0000) == 0xe59f0000);+ buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr;+#else+ SLJIT_ASSERT((buf_ptr[-1] & 0xfff00000) == MOVW && (buf_ptr[0] & 0xfff00000) == MOVT);+ buf_ptr[-1] |= ((addr << 4) & 0xf0000) | (addr & 0xfff);+ buf_ptr[0] |= ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff);+#endif+ put_label = put_label->next;+ }++ SLJIT_ASSERT(code_ptr - code <= (sljit_s32)size);++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (code_ptr - code) * sizeof(sljit_uw);++ code = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);+ code_ptr = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ SLJIT_CACHE_FLUSH(code, code_ptr);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ return code;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ switch (feature_type) {+ case SLJIT_HAS_FPU:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return SLJIT_IS_FPU_AVAILABLE;+#else+ /* Available by default. */+ return 1;+#endif++ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_CMOV:+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ case SLJIT_HAS_PREFETCH:+#endif+ return 1;++ default:+ return 0;+ }+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++/* Creates an index in data_transfer_insts array. */+#define WORD_SIZE 0x00+#define BYTE_SIZE 0x01+#define HALF_SIZE 0x02+#define PRELOAD 0x03+#define SIGNED 0x04+#define LOAD_DATA 0x08++/* Flag bits for emit_op. */+#define ALLOW_IMM 0x10+#define ALLOW_INV_IMM 0x20+#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM)++/* s/l - store/load (1 bit)+ u/s - signed/unsigned (1 bit)+ w/b/h/N - word/byte/half/NOT allowed (2 bit)+ Storing signed and unsigned values are the same operations. */++static const sljit_uw data_transfer_insts[16] = {+/* s u w */ 0xe5000000 /* str */,+/* s u b */ 0xe5400000 /* strb */,+/* s u h */ 0xe10000b0 /* strh */,+/* s u N */ 0x00000000 /* not allowed */,+/* s s w */ 0xe5000000 /* str */,+/* s s b */ 0xe5400000 /* strb */,+/* s s h */ 0xe10000b0 /* strh */,+/* s s N */ 0x00000000 /* not allowed */,++/* l u w */ 0xe5100000 /* ldr */,+/* l u b */ 0xe5500000 /* ldrb */,+/* l u h */ 0xe11000b0 /* ldrh */,+/* l u p */ 0xf5500000 /* preload */,+/* l s w */ 0xe5100000 /* ldr */,+/* l s b */ 0xe11000d0 /* ldrsb */,+/* l s h */ 0xe11000f0 /* ldrsh */,+/* l s N */ 0x00000000 /* not allowed */,+};++#define EMIT_DATA_TRANSFER(type, add, target_reg, base_reg, arg) \+ (data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (arg))++/* Normal ldr/str instruction.+ Type2: ldrsb, ldrh, ldrsh */+#define IS_TYPE1_TRANSFER(type) \+ (data_transfer_insts[(type) & 0xf] & 0x04000000)+#define TYPE2_TRANSFER_IMM(imm) \+ (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))++static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 args, size, i, tmp;+ sljit_uw push;++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ /* Push saved registers, temporary registers+ stmdb sp!, {..., lr} */+ push = PUSH | (1 << 14);++ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = SLJIT_S0; i >= tmp; i--)+ push |= 1 << reg_map[i];++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)+ push |= 1 << reg_map[i];++ FAIL_IF(push_inst(compiler, push));++ /* Stack must be aligned to 8 bytes: */+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);+ local_size = ((size + local_size + 7) & ~7) - size;+ compiler->local_size = local_size;+ if (local_size > 0)+ FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));++ args = get_arg_count(arg_types);++ if (args >= 1)+ FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0) | RM(SLJIT_R0)));+ if (args >= 2)+ FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S1) | RM(SLJIT_R1)));+ if (args >= 3)+ FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S2) | RM(SLJIT_R2)));++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);+ compiler->local_size = ((size + local_size + 7) & ~7) - size;+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 i, tmp;+ sljit_uw pop;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));++ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));++ if (compiler->local_size > 0)+ FAIL_IF(emit_op(compiler, SLJIT_ADD, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));++ /* Push saved registers, temporary registers+ ldmia sp!, {..., pc} */+ pop = POP | (1 << 15);++ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = SLJIT_S0; i >= tmp; i--)+ pop |= 1 << reg_map[i];++ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--)+ pop |= 1 << reg_map[i];++ return push_inst(compiler, pop);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++/* flags: */+ /* Arguments are swapped. */+#define ARGS_SWAPPED 0x01+ /* Inverted immediate. */+#define INV_IMM 0x02+ /* Source and destination is register. */+#define MOVE_REG_CONV 0x04+ /* Unused return value. */+#define UNUSED_RETURN 0x08+/* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */+#define SET_FLAGS (1 << 20)+/* dst: reg+ src1: reg+ src2: reg or imm (if allowed)+ SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */+#define SRC2_IMM (1 << 25)++#define EMIT_SHIFT_INS_AND_RETURN(opcode) \+ SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \+ if (compiler->shift_imm != 0x20) { \+ SLJIT_ASSERT(src1 == TMP_REG1); \+ SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \+ \+ if (compiler->shift_imm != 0) \+ return push_inst(compiler, MOV | (flags & SET_FLAGS) | \+ RD(dst) | (compiler->shift_imm << 7) | (opcode << 5) | RM(src2)); \+ return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2)); \+ } \+ return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | \+ (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1));++static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,+ sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)+{+ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));+ if (dst != src2) {+ if (src2 & SRC2_IMM) {+ return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);+ }+ return push_inst(compiler, MOV | RD(dst) | RM(src2));+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));+ if (flags & MOVE_REG_CONV) {+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ if (op == SLJIT_MOV_U8)+ return push_inst(compiler, AND | RD(dst) | RN(src2) | SRC2_IMM | 0xff);+ FAIL_IF(push_inst(compiler, MOV | RD(dst) | (24 << 7) | RM(src2)));+ return push_inst(compiler, MOV | RD(dst) | (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | RM(dst));+#else+ return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2));+#endif+ }+ else if (dst != src2) {+ SLJIT_ASSERT(src2 & SRC2_IMM);+ return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));+ if (flags & MOVE_REG_CONV) {+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ FAIL_IF(push_inst(compiler, MOV | RD(dst) | (16 << 7) | RM(src2)));+ return push_inst(compiler, MOV | RD(dst) | (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | RM(dst));+#else+ return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2));+#endif+ }+ else if (dst != src2) {+ SLJIT_ASSERT(src2 & SRC2_IMM);+ return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_NOT:+ if (src2 & SRC2_IMM) {+ return push_inst(compiler, ((flags & INV_IMM) ? MOV : MVN) | (flags & SET_FLAGS) | RD(dst) | src2);+ }+ return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src2));++ case SLJIT_CLZ:+ SLJIT_ASSERT(!(flags & INV_IMM));+ SLJIT_ASSERT(!(src2 & SRC2_IMM));+ FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));+ return SLJIT_SUCCESS;++ case SLJIT_ADD:+ SLJIT_ASSERT(!(flags & INV_IMM));+ if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))+ return push_inst(compiler, CMN | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));+ return push_inst(compiler, ADD | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_ADDC:+ SLJIT_ASSERT(!(flags & INV_IMM));+ return push_inst(compiler, ADC | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_SUB:+ SLJIT_ASSERT(!(flags & INV_IMM));+ if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))+ return push_inst(compiler, CMP | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));+ return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SUB : RSB) | (flags & SET_FLAGS)+ | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_SUBC:+ SLJIT_ASSERT(!(flags & INV_IMM));+ return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SBC : RSC) | (flags & SET_FLAGS)+ | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_MUL:+ SLJIT_ASSERT(!(flags & INV_IMM));+ SLJIT_ASSERT(!(src2 & SRC2_IMM));++ if (!HAS_FLAGS(op))+ return push_inst(compiler, MUL | (reg_map[dst] << 16) | (reg_map[src2] << 8) | reg_map[src1]);++ FAIL_IF(push_inst(compiler, SMULL | (reg_map[TMP_REG1] << 16) | (reg_map[dst] << 12) | (reg_map[src2] << 8) | reg_map[src1]));++ /* cmp TMP_REG1, dst asr #31. */+ return push_inst(compiler, CMP | SET_FLAGS | RN(TMP_REG1) | RM(dst) | 0xfc0);++ case SLJIT_AND:+ return push_inst(compiler, (!(flags & INV_IMM) ? AND : BIC) | (flags & SET_FLAGS)+ | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_OR:+ SLJIT_ASSERT(!(flags & INV_IMM));+ return push_inst(compiler, ORR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_XOR:+ SLJIT_ASSERT(!(flags & INV_IMM));+ return push_inst(compiler, EOR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));++ case SLJIT_SHL:+ EMIT_SHIFT_INS_AND_RETURN(0);++ case SLJIT_LSHR:+ EMIT_SHIFT_INS_AND_RETURN(1);++ case SLJIT_ASHR:+ EMIT_SHIFT_INS_AND_RETURN(2);+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++#undef EMIT_SHIFT_INS_AND_RETURN++/* Tests whether the immediate can be stored in the 12 bit imm field.+ Returns with 0 if not possible. */+static sljit_uw get_imm(sljit_uw imm)+{+ sljit_s32 rol;++ if (imm <= 0xff)+ return SRC2_IMM | imm;++ if (!(imm & 0xff000000)) {+ imm <<= 8;+ rol = 8;+ }+ else {+ imm = (imm << 24) | (imm >> 8);+ rol = 0;+ }++ if (!(imm & 0xff000000)) {+ imm <<= 8;+ rol += 4;+ }++ if (!(imm & 0xf0000000)) {+ imm <<= 4;+ rol += 2;+ }++ if (!(imm & 0xc0000000)) {+ imm <<= 2;+ rol += 1;+ }++ if (!(imm & 0x00ffffff))+ return SRC2_IMM | (imm >> 24) | (rol << 8);+ else+ return 0;+}++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm, sljit_s32 positive)+{+ sljit_uw mask;+ sljit_uw imm1;+ sljit_uw imm2;+ sljit_s32 rol;++ /* Step1: Search a zero byte (8 continous zero bit). */+ mask = 0xff000000;+ rol = 8;+ while(1) {+ if (!(imm & mask)) {+ /* Rol imm by rol. */+ imm = (imm << rol) | (imm >> (32 - rol));+ /* Calculate arm rol. */+ rol = 4 + (rol >> 1);+ break;+ }+ rol += 2;+ mask >>= 2;+ if (mask & 0x3) {+ /* rol by 8. */+ imm = (imm << 8) | (imm >> 24);+ mask = 0xff00;+ rol = 24;+ while (1) {+ if (!(imm & mask)) {+ /* Rol imm by rol. */+ imm = (imm << rol) | (imm >> (32 - rol));+ /* Calculate arm rol. */+ rol = (rol >> 1) - 8;+ break;+ }+ rol += 2;+ mask >>= 2;+ if (mask & 0x3)+ return 0;+ }+ break;+ }+ }++ /* The low 8 bit must be zero. */+ SLJIT_ASSERT(!(imm & 0xff));++ if (!(imm & 0xff000000)) {+ imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8);+ imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8);+ }+ else if (imm & 0xc0000000) {+ imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);+ imm <<= 8;+ rol += 4;++ if (!(imm & 0xff000000)) {+ imm <<= 8;+ rol += 4;+ }++ if (!(imm & 0xf0000000)) {+ imm <<= 4;+ rol += 2;+ }++ if (!(imm & 0xc0000000)) {+ imm <<= 2;+ rol += 1;+ }++ if (!(imm & 0x00ffffff))+ imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);+ else+ return 0;+ }+ else {+ if (!(imm & 0xf0000000)) {+ imm <<= 4;+ rol += 2;+ }++ if (!(imm & 0xc0000000)) {+ imm <<= 2;+ rol += 1;+ }++ imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);+ imm <<= 8;+ rol += 4;++ if (!(imm & 0xf0000000)) {+ imm <<= 4;+ rol += 2;+ }++ if (!(imm & 0xc0000000)) {+ imm <<= 2;+ rol += 1;+ }++ if (!(imm & 0x00ffffff))+ imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);+ else+ return 0;+ }++ FAIL_IF(push_inst(compiler, (positive ? MOV : MVN) | RD(reg) | imm1));+ FAIL_IF(push_inst(compiler, (positive ? ORR : BIC) | RD(reg) | RN(reg) | imm2));+ return 1;+}+#endif++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm)+{+ sljit_uw tmp;++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ if (!(imm & ~0xffff))+ return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff));+#endif++ /* Create imm by 1 inst. */+ tmp = get_imm(imm);+ if (tmp)+ return push_inst(compiler, MOV | RD(reg) | tmp);++ tmp = get_imm(~imm);+ if (tmp)+ return push_inst(compiler, MVN | RD(reg) | tmp);++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ /* Create imm by 2 inst. */+ FAIL_IF(generate_int(compiler, reg, imm, 1));+ FAIL_IF(generate_int(compiler, reg, ~imm, 0));++ /* Load integer. */+ return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), imm);+#else+ FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));+ if (imm <= 0xffff)+ return SLJIT_SUCCESS;+ return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));+#endif+}++static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)+{+ sljit_uw imm, offset_reg;+ sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags);++ SLJIT_ASSERT (arg & SLJIT_MEM);+ SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);++ if ((arg & REG_MASK) == SLJIT_UNUSED) {+ if (is_type1_transfer) {+ FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xfff));+ argw &= 0xfff;+ }+ else {+ FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xff));+ argw &= 0xff;+ }++ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg,+ is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw)));+ }++ if (arg & OFFS_REG_MASK) {+ offset_reg = OFFS_REG(arg);+ arg &= REG_MASK;+ argw &= 0x3;++ if (argw != 0 && !is_type1_transfer) {+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | (argw << 7)));+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));+ }++ /* Bit 25: RM is offset. */+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,+ RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | (argw << 7)));+ }++ arg &= REG_MASK;++ if (is_type1_transfer) {+ if (argw > 0xfff) {+ imm = get_imm(argw & ~0xfff);+ if (imm) {+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));+ argw = argw & 0xfff;+ arg = tmp_reg;+ }+ }+ else if (argw < -0xfff) {+ imm = get_imm(-argw & ~0xfff);+ if (imm) {+ FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));+ argw = -(-argw & 0xfff);+ arg = tmp_reg;+ }+ }++ if (argw >= 0 && argw <= 0xfff)+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));++ if (argw < 0 && argw >= -0xfff)+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, -argw));+ }+ else {+ if (argw > 0xff) {+ imm = get_imm(argw & ~0xff);+ if (imm) {+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));+ argw = argw & 0xff;+ arg = tmp_reg;+ }+ }+ else if (argw < -0xff) {+ imm = get_imm(-argw & ~0xff);+ if (imm) {+ FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));+ argw = -(-argw & 0xff);+ arg = tmp_reg;+ }+ }++ if (argw >= 0 && argw <= 0xff)+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, TYPE2_TRANSFER_IMM(argw)));++ if (argw < 0 && argw >= -0xff) {+ argw = -argw;+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, TYPE2_TRANSFER_IMM(argw)));+ }+ }++ FAIL_IF(load_immediate(compiler, tmp_reg, argw));+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,+ RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0)));+}++static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ /* src1 is reg or TMP_REG1+ src2 is reg, TMP_REG2, or imm+ result goes to TMP_REG2, so put result can use TMP_REG1. */++ /* We prefers register and simple consts. */+ sljit_s32 dst_reg;+ sljit_s32 src1_reg;+ sljit_s32 src2_reg;+ sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;++ /* Destination check. */+ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED))+ flags |= UNUSED_RETURN;++ SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));++ src2_reg = 0;++ do {+ if (!(inp_flags & ALLOW_IMM))+ break;++ if (src2 & SLJIT_IMM) {+ src2_reg = get_imm(src2w);+ if (src2_reg)+ break;+ if (inp_flags & ALLOW_INV_IMM) {+ src2_reg = get_imm(~src2w);+ if (src2_reg) {+ flags |= INV_IMM;+ break;+ }+ }+ if (GET_OPCODE(op) == SLJIT_ADD) {+ src2_reg = get_imm(-src2w);+ if (src2_reg) {+ op = SLJIT_SUB | GET_ALL_FLAGS(op);+ break;+ }+ }+ if (GET_OPCODE(op) == SLJIT_SUB) {+ src2_reg = get_imm(-src2w);+ if (src2_reg) {+ op = SLJIT_ADD | GET_ALL_FLAGS(op);+ break;+ }+ }+ }++ if (src1 & SLJIT_IMM) {+ src2_reg = get_imm(src1w);+ if (src2_reg) {+ flags |= ARGS_SWAPPED;+ src1 = src2;+ src1w = src2w;+ break;+ }+ if (inp_flags & ALLOW_INV_IMM) {+ src2_reg = get_imm(~src1w);+ if (src2_reg) {+ flags |= ARGS_SWAPPED | INV_IMM;+ src1 = src2;+ src1w = src2w;+ break;+ }+ }+ if (GET_OPCODE(op) == SLJIT_ADD) {+ src2_reg = get_imm(-src1w);+ if (src2_reg) {+ /* Note: add is commutative operation. */+ src1 = src2;+ src1w = src2w;+ op = SLJIT_SUB | GET_ALL_FLAGS(op);+ break;+ }+ }+ }+ } while(0);++ /* Source 1. */+ if (FAST_IS_REG(src1))+ src1_reg = src1;+ else if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));+ src1_reg = TMP_REG1;+ }+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));+ src1_reg = TMP_REG1;+ }++ /* Destination. */+ dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;++ if (op <= SLJIT_MOV_P) {+ if (dst & SLJIT_MEM) {+ if (inp_flags & BYTE_SIZE)+ inp_flags &= ~SIGNED;++ if (FAST_IS_REG(src2))+ return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG2);+ }++ if (FAST_IS_REG(src2) && dst_reg != TMP_REG2)+ flags |= MOVE_REG_CONV;+ }++ /* Source 2. */+ if (src2_reg == 0) {+ src2_reg = (op <= SLJIT_MOV_P) ? dst_reg : TMP_REG2;++ if (FAST_IS_REG(src2))+ src2_reg = src2;+ else if (src2 & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG2));+ else+ FAIL_IF(load_immediate(compiler, src2_reg, src2w));+ }++ FAIL_IF(emit_single_op(compiler, op, flags, dst_reg, src1_reg, src2_reg));++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;++ return emit_op_mem(compiler, inp_flags, dst_reg, dst, dstw, TMP_REG1);+}++#ifdef __cplusplus+extern "C" {+#endif++#if defined(__GNUC__)+extern unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator);+extern int __aeabi_idivmod(int numerator, int denominator);+#else+#error "Software divmod functions are needed"+#endif++#ifdef __cplusplus+}+#endif++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+ sljit_sw saved_reg_list[3];+ sljit_sw saved_reg_count;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ FAIL_IF(push_inst(compiler, BKPT));+ break;+ case SLJIT_NOP:+ FAIL_IF(push_inst(compiler, NOP));+ break;+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+ return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)+ | (reg_map[SLJIT_R1] << 16)+ | (reg_map[SLJIT_R0] << 12)+ | (reg_map[SLJIT_R0] << 8)+ | reg_map[SLJIT_R1]);+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIVMOD_SW:+ case SLJIT_DIV_UW:+ case SLJIT_DIV_SW:+ SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);+ SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3);++ saved_reg_count = 0;+ if (compiler->scratches >= 4)+ saved_reg_list[saved_reg_count++] = 3;+ if (compiler->scratches >= 3)+ saved_reg_list[saved_reg_count++] = 2;+ if (op >= SLJIT_DIV_UW)+ saved_reg_list[saved_reg_count++] = 1;++ if (saved_reg_count > 0) {+ FAIL_IF(push_inst(compiler, 0xe52d0000 | (saved_reg_count >= 3 ? 16 : 8)+ | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));+ if (saved_reg_count >= 2) {+ SLJIT_ASSERT(saved_reg_list[1] < 8);+ FAIL_IF(push_inst(compiler, 0xe58d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */));+ }+ if (saved_reg_count >= 3) {+ SLJIT_ASSERT(saved_reg_list[2] < 8);+ FAIL_IF(push_inst(compiler, 0xe58d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));+ }+ }++#if defined(__GNUC__)+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));+#else+#error "Software divmod functions are needed"+#endif++ if (saved_reg_count > 0) {+ if (saved_reg_count >= 3) {+ SLJIT_ASSERT(saved_reg_list[2] < 8);+ FAIL_IF(push_inst(compiler, 0xe59d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */));+ }+ if (saved_reg_count >= 2) {+ SLJIT_ASSERT(saved_reg_list[1] < 8);+ FAIL_IF(push_inst(compiler, 0xe59d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));+ }+ return push_inst(compiler, 0xe49d0000 | (saved_reg_count >= 3 ? 16 : 8)+ | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);+ }+ return SLJIT_SUCCESS;+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV_P:+ return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOV_U8:+ return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);++ case SLJIT_MOV_S8:+ return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);++ case SLJIT_MOV_U16:+ return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);++ case SLJIT_MOV_S16:+ return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);++ case SLJIT_NOT:+ return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_NEG:+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ return sljit_emit_op2(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), dst, dstw, SLJIT_IMM, 0, src, srcw);++ case SLJIT_CLZ:+ return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))+ return SLJIT_SUCCESS;++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ case SLJIT_ADDC:+ case SLJIT_SUB:+ case SLJIT_SUBC:+ case SLJIT_OR:+ case SLJIT_XOR:+ return emit_op(compiler, op, ALLOW_IMM, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_MUL:+ return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_AND:+ return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SHL:+ case SLJIT_LSHR:+ case SLJIT_ASHR:+ if (src2 & SLJIT_IMM) {+ compiler->shift_imm = src2w & 0x1f;+ return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w);+ }+ else {+ compiler->shift_imm = 0x20;+ return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);+ }+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));++ return push_inst(compiler, BX | RM(TMP_REG2));+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ SLJIT_ASSERT(src & SLJIT_MEM);+ return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);+#else /* !SLJIT_CONFIG_ARM_V7 */+ return SLJIT_SUCCESS;+#endif /* SLJIT_CONFIG_ARM_V7 */+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(reg));+ return reg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));+ return (freg_map[reg] << 1);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_uw*)instruction);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */+++#define FPU_LOAD (1 << 20)+#define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \+ ((inst) | ((add) << 23) | (reg_map[base] << 16) | (freg_map[freg] << 12) | (offs))+#define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \+ ((opcode) | (mode) | (freg_map[dst] << 12) | freg_map[src1] | (freg_map[src2] << 16))++static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ sljit_uw imm;+ sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD));++ SLJIT_ASSERT(arg & SLJIT_MEM);+ arg &= ~SLJIT_MEM;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((argw & 0x3) << 7)));+ arg = TMP_REG2;+ argw = 0;+ }++ /* Fast loads and stores. */+ if (arg) {+ if (!(argw & ~0x3fc))+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & REG_MASK, reg, argw >> 2));+ if (!(-argw & ~0x3fc))+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2));++ imm = get_imm(argw & ~0x3fc);+ if (imm) {+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | imm));+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, (argw & 0x3fc) >> 2));+ }+ imm = get_imm(-argw & ~0x3fc);+ if (imm) {+ argw = -argw;+ FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG2) | RN(arg & REG_MASK) | imm));+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG2, reg, (argw & 0x3fc) >> 2));+ }+ }++ if (arg) {+ FAIL_IF(load_immediate(compiler, TMP_REG2, argw));+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(TMP_REG2)));+ }+ else+ FAIL_IF(load_immediate(compiler, TMP_REG2, argw));++ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, 0));+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ op ^= SLJIT_F32_OP;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw));+ src = TMP_FREG1;+ }++ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_F32_OP, TMP_FREG1, src, 0)));++ if (FAST_IS_REG(dst))+ return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | (freg_map[TMP_FREG1] << 16));++ /* Store the integer value from a VFP register. */+ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ op ^= SLJIT_F32_OP;++ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, VMOV | RD(src) | (freg_map[TMP_FREG1] << 16)));+ else if (src & SLJIT_MEM) {+ /* Load the integer value into a VFP register. */+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));+ }+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | (freg_map[TMP_FREG1] << 16)));+ }++ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_F32_OP, dst_r, TMP_FREG1, 0)));++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ op ^= SLJIT_F32_OP;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));+ src2 = TMP_FREG2;+ }++ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_F32_OP, src1, src2, 0)));+ return push_inst(compiler, VMRS);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r;++ CHECK_ERROR();++ SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)+ op ^= SLJIT_F32_OP;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (dst_r != TMP_FREG1)+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_F32_OP, dst_r, src, 0)));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_F32_OP, dst_r, src, 0)));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_F32_OP, dst_r, src, 0)));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_F32_OP, dst_r, src, 0)));+ op ^= SLJIT_F32_OP;+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, (op & SLJIT_F32_OP), dst_r, dst, dstw);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ op ^= SLJIT_F32_OP;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));+ src2 = TMP_FREG2;+ }++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));+ src1 = TMP_FREG1;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));+ break;++ case SLJIT_SUB_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));+ break;++ case SLJIT_MUL_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));+ break;++ case SLJIT_DIV_F64:+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));+ break;+ }++ if (dst_r == TMP_FREG1)+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw));++ return SLJIT_SUCCESS;+}++#undef FPU_LOAD+#undef EMIT_FPU_DATA_TRANSFER++/* --------------------------------------------------------------------- */+/* Other instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ if (FAST_IS_REG(dst))+ return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2));++ /* Memory. */+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++static sljit_uw get_cc(sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_MUL_NOT_OVERFLOW:+ case SLJIT_EQUAL_F64:+ return 0x00000000;++ case SLJIT_NOT_EQUAL:+ case SLJIT_MUL_OVERFLOW:+ case SLJIT_NOT_EQUAL_F64:+ return 0x10000000;++ case SLJIT_LESS:+ case SLJIT_LESS_F64:+ return 0x30000000;++ case SLJIT_GREATER_EQUAL:+ case SLJIT_GREATER_EQUAL_F64:+ return 0x20000000;++ case SLJIT_GREATER:+ case SLJIT_GREATER_F64:+ return 0x80000000;++ case SLJIT_LESS_EQUAL:+ case SLJIT_LESS_EQUAL_F64:+ return 0x90000000;++ case SLJIT_SIG_LESS:+ return 0xb0000000;++ case SLJIT_SIG_GREATER_EQUAL:+ return 0xa0000000;++ case SLJIT_SIG_GREATER:+ return 0xc0000000;++ case SLJIT_SIG_LESS_EQUAL:+ return 0xd0000000;++ case SLJIT_OVERFLOW:+ case SLJIT_UNORDERED_F64:+ return 0x60000000;++ case SLJIT_NOT_OVERFLOW:+ case SLJIT_ORDERED_F64:+ return 0x70000000;++ default:+ SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);+ return 0xe0000000;+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ if (type >= SLJIT_FAST_CALL)+ PTR_FAIL_IF(prepare_blx(compiler));+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,+ type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0));++ if (jump->flags & SLJIT_REWRITABLE_JUMP) {+ jump->addr = compiler->size;+ compiler->patches++;+ }++ if (type >= SLJIT_FAST_CALL) {+ jump->flags |= IS_BL;+ PTR_FAIL_IF(emit_blx(compiler));+ }++ if (!(jump->flags & SLJIT_REWRITABLE_JUMP))+ jump->addr = compiler->size;+#else+ if (type >= SLJIT_FAST_CALL)+ jump->flags |= IS_BL;+ PTR_FAIL_IF(emit_imm(compiler, TMP_REG1, 0));+ PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(type)));+ jump->addr = compiler->size;+#endif+ return jump;+}++#ifdef __SOFTFP__++static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)+{+ sljit_s32 stack_offset = 0;+ sljit_s32 arg_count = 0;+ sljit_s32 word_arg_offset = 0;+ sljit_s32 float_arg_count = 0;+ sljit_s32 types = 0;+ sljit_s32 src_offset = 4 * sizeof(sljit_sw);+ sljit_u8 offsets[4];++ if (src && FAST_IS_REG(*src))+ src_offset = reg_map[*src] * sizeof(sljit_sw);++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);++ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ offsets[arg_count] = (sljit_u8)stack_offset;+ stack_offset += sizeof(sljit_f32);+ arg_count++;+ float_arg_count++;+ break;+ case SLJIT_ARG_TYPE_F64:+ if (stack_offset & 0x7)+ stack_offset += sizeof(sljit_sw);+ offsets[arg_count] = (sljit_u8)stack_offset;+ stack_offset += sizeof(sljit_f64);+ arg_count++;+ float_arg_count++;+ break;+ default:+ offsets[arg_count] = (sljit_u8)stack_offset;+ stack_offset += sizeof(sljit_sw);+ arg_count++;+ word_arg_offset += sizeof(sljit_sw);+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ if (stack_offset > 16)+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | (((stack_offset - 16) + 0x7) & ~0x7)));++ /* Process arguments in reversed direction. */+ while (types) {+ switch (types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ arg_count--;+ float_arg_count--;+ stack_offset = offsets[arg_count];++ if (stack_offset < 16) {+ if (src_offset == stack_offset) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));+ *src = TMP_REG1;+ }+ FAIL_IF(push_inst(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (stack_offset << 10)));+ } else+ FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800000 | RN(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2)));+ break;+ case SLJIT_ARG_TYPE_F64:+ arg_count--;+ float_arg_count--;+ stack_offset = offsets[arg_count];++ SLJIT_ASSERT((stack_offset & 0x7) == 0);++ if (stack_offset < 16) {+ if (src_offset == stack_offset || src_offset == stack_offset + sizeof(sljit_sw)) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));+ *src = TMP_REG1;+ }+ FAIL_IF(push_inst(compiler, VMOV2 | 0x100000 | (stack_offset << 10) | ((stack_offset + sizeof(sljit_sw)) << 14) | float_arg_count));+ } else+ FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800100 | RN(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2)));+ break;+ default:+ arg_count--;+ word_arg_offset -= sizeof(sljit_sw);+ stack_offset = offsets[arg_count];++ SLJIT_ASSERT(stack_offset >= word_arg_offset);++ if (stack_offset != word_arg_offset) {+ if (stack_offset < 16) {+ if (src_offset == stack_offset) {+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));+ *src = TMP_REG1;+ }+ else if (src_offset == word_arg_offset) {+ *src = 1 + (stack_offset >> 2);+ src_offset = stack_offset;+ }+ FAIL_IF(push_inst(compiler, MOV | (stack_offset << 10) | (word_arg_offset >> 2)));+ } else+ FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (stack_offset - 16)));+ }+ break;+ }++ types >>= SLJIT_DEF_SHIFT;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)+{+ sljit_s32 stack_size = 0;++ if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32)+ FAIL_IF(push_inst(compiler, VMOV | (0 << 16) | (0 << 12)));+ if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64)+ FAIL_IF(push_inst(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ stack_size += sizeof(sljit_f32);+ break;+ case SLJIT_ARG_TYPE_F64:+ if (stack_size & 0x7)+ stack_size += sizeof(sljit_sw);+ stack_size += sizeof(sljit_f64);+ break;+ default:+ stack_size += sizeof(sljit_sw);+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ if (stack_size <= 16)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | (((stack_size - 16) + 0x7) & ~0x7));+}++#else /* !__SOFTFP__ */++static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)+{+ sljit_u32 remap = 0;+ sljit_u32 offset = 0;+ sljit_u32 new_offset, mask;++ /* Remove return value. */+ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) {+ new_offset = 0;+ mask = 1;++ while (remap & mask) {+ new_offset++;+ mask <<= 1;+ }+ remap |= mask;++ if (offset != new_offset)+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,+ 0, (new_offset >> 1) + 1, (offset >> 1) + 1, 0) | ((new_offset & 0x1) ? 0x400000 : 0)));++ offset += 2;+ }+ else if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) {+ new_offset = 0;+ mask = 3;++ while (remap & mask) {+ new_offset += 2;+ mask <<= 2;+ }+ remap |= mask;++ if (offset != new_offset)+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, SLJIT_F32_OP, (new_offset >> 1) + 1, (offset >> 1) + 1, 0)));++ offset += 2;+ }+ arg_types >>= SLJIT_DEF_SHIFT;+ }++ return SLJIT_SUCCESS;+}++#endif /* __SOFTFP__ */++#undef EMIT_FPU_OPERATION++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+#ifdef __SOFTFP__+ struct sljit_jump *jump;+#endif++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++#ifdef __SOFTFP__+ PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ jump = sljit_emit_jump(compiler, type);+ PTR_FAIL_IF(jump == NULL);++ PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));+ return jump;+#else /* !__SOFTFP__ */+ PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_jump(compiler, type);+#endif /* __SOFTFP__ */+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ struct sljit_jump *jump;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);++ if (!(src & SLJIT_IMM)) {+ if (FAST_IS_REG(src)) {+ SLJIT_ASSERT(reg_map[src] != 14);+ return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));+ }++ SLJIT_ASSERT(src & SLJIT_MEM);+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1));+ }++ /* These jumps are converted to jump/call instructions when possible. */+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));+ jump->u.target = srcw;++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ if (type >= SLJIT_FAST_CALL)+ FAIL_IF(prepare_blx(compiler));+ FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));+ if (type >= SLJIT_FAST_CALL)+ FAIL_IF(emit_blx(compiler));+#else+ FAIL_IF(emit_imm(compiler, TMP_REG1, 0));+ FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));+#endif+ jump->addr = compiler->size;+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++#ifdef __SOFTFP__+ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));++ return softfloat_post_call_with_args(compiler, arg_types);+#else /* !__SOFTFP__ */+ FAIL_IF(hardfloat_call_with_args(compiler, arg_types));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_ijump(compiler, type, src, srcw);+#endif /* __SOFTFP__ */+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 type)+{+ sljit_s32 dst_reg, flags = GET_ALL_FLAGS(op);+ sljit_uw cc, ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ op = GET_OPCODE(op);+ cc = get_cc(type & 0xff);+ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (op < SLJIT_ADD) {+ FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | SRC2_IMM | 0));+ FAIL_IF(push_inst(compiler, ((MOV | RD(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));+ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+ }++ ins = (op == SLJIT_AND ? AND : (op == SLJIT_OR ? ORR : EOR));++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2));++ FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));++ if (op == SLJIT_AND)+ FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));++ if (flags & SLJIT_SET_Z)+ return push_inst(compiler, MOV | SET_FLAGS | RD(TMP_REG2) | RM(dst_reg));+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_uw cc, tmp;++ CHECK_ERROR();+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));++ dst_reg &= ~SLJIT_I32_OP;++ cc = get_cc(type & 0xff);++ if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {+ tmp = get_imm(srcw);+ if (tmp)+ return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc);++ tmp = get_imm(~srcw);+ if (tmp)+ return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc);++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ tmp = (sljit_uw) srcw;+ FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff)));+ if (tmp <= 0xffff)+ return SLJIT_SUCCESS;+ return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff));+#else+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+#endif+ }++ return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src)) & ~COND_MASK) | cc);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 flags;+ sljit_uw is_type1_transfer, inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ is_type1_transfer = 1;++ switch (type & 0xff) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV_P:+ flags = WORD_SIZE;+ break;+ case SLJIT_MOV_U8:+ flags = BYTE_SIZE;+ break;+ case SLJIT_MOV_S8:+ if (!(type & SLJIT_MEM_STORE))+ is_type1_transfer = 0;+ flags = BYTE_SIZE | SIGNED;+ break;+ case SLJIT_MOV_U16:+ is_type1_transfer = 0;+ flags = HALF_SIZE;+ break;+ case SLJIT_MOV_S16:+ is_type1_transfer = 0;+ flags = HALF_SIZE | SIGNED;+ break;+ default:+ SLJIT_UNREACHABLE();+ flags = WORD_SIZE;+ break;+ }++ if (!(type & SLJIT_MEM_STORE))+ flags |= LOAD_DATA;++ SLJIT_ASSERT(is_type1_transfer == !!IS_TYPE1_TRANSFER(flags));++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ if (!is_type1_transfer && memw != 0)+ return SLJIT_ERR_UNSUPPORTED;+ }+ else {+ if (is_type1_transfer) {+ if (memw > 4095 || memw < -4095)+ return SLJIT_ERR_UNSUPPORTED;+ }+ else {+ if (memw > 255 || memw < -255)+ return SLJIT_ERR_UNSUPPORTED;+ }+ }++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ memw &= 0x3;++ inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | (memw << 7));++ if (is_type1_transfer)+ inst |= (1 << 25);++ if (type & SLJIT_MEM_PRE)+ inst |= (1 << 21);+ else+ inst ^= (1 << 24);++ return push_inst(compiler, inst);+ }++ inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0);++ if (type & SLJIT_MEM_PRE)+ inst |= (1 << 21);+ else+ inst ^= (1 << 24);++ if (is_type1_transfer) {+ if (memw >= 0)+ inst |= (1 << 23);+ else+ memw = -memw;++ return push_inst(compiler, inst | memw);+ }++ if (memw >= 0)+ inst |= (1 << 23);+ else+ memw = -memw;++ return push_inst(compiler, inst | TYPE2_TRANSFER_IMM(memw));+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG2;++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), init_value));+ compiler->patches++;+#else+ PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));+#endif++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));+ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_put_label *put_label;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG2;++#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0));+ compiler->patches++;+#else+ PTR_FAIL_IF(emit_imm(compiler, dst_r, 0));+#endif++ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));+ PTR_FAIL_IF(!put_label);+ set_put_label(put_label, compiler, 0);++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));+ return put_label;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ inline_set_jump_addr(addr, executable_offset, new_target, 1);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ inline_set_const(addr, executable_offset, new_constant, 1);+}
+ src/c/pcre2/src/sljit/sljitNativeARM_64.c view
@@ -0,0 +1,2048 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+ return "ARM-64" SLJIT_CPUINFO;+}++/* Length of an instruction word */+typedef sljit_u32 sljit_ins;++#define TMP_ZERO (0)++#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)+#define TMP_LR (SLJIT_NUMBER_OF_REGISTERS + 4)+#define TMP_FP (SLJIT_NUMBER_OF_REGISTERS + 5)++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)++/* r18 - platform register, currently not used */+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {+ 31, 0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 31, 9, 10, 30, 29+};++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {+ 0, 0, 1, 2, 3, 4, 5, 6, 7+};++#define W_OP (1u << 31)+#define RD(rd) (reg_map[rd])+#define RT(rt) (reg_map[rt])+#define RN(rn) (reg_map[rn] << 5)+#define RT2(rt2) (reg_map[rt2] << 10)+#define RM(rm) (reg_map[rm] << 16)+#define VD(vd) (freg_map[vd])+#define VT(vt) (freg_map[vt])+#define VN(vn) (freg_map[vn] << 5)+#define VM(vm) (freg_map[vm] << 16)++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++#define ADC 0x9a000000+#define ADD 0x8b000000+#define ADDE 0x8b200000+#define ADDI 0x91000000+#define AND 0x8a000000+#define ANDI 0x92000000+#define ASRV 0x9ac02800+#define B 0x14000000+#define B_CC 0x54000000+#define BL 0x94000000+#define BLR 0xd63f0000+#define BR 0xd61f0000+#define BRK 0xd4200000+#define CBZ 0xb4000000+#define CLZ 0xdac01000+#define CSEL 0x9a800000+#define CSINC 0x9a800400+#define EOR 0xca000000+#define EORI 0xd2000000+#define FABS 0x1e60c000+#define FADD 0x1e602800+#define FCMP 0x1e602000+#define FCVT 0x1e224000+#define FCVTZS 0x9e780000+#define FDIV 0x1e601800+#define FMOV 0x1e604000+#define FMUL 0x1e600800+#define FNEG 0x1e614000+#define FSUB 0x1e603800+#define LDRI 0xf9400000+#define LDP 0xa9400000+#define LDP_PRE 0xa9c00000+#define LDR_PRE 0xf8400c00+#define LSLV 0x9ac02000+#define LSRV 0x9ac02400+#define MADD 0x9b000000+#define MOVK 0xf2800000+#define MOVN 0x92800000+#define MOVZ 0xd2800000+#define NOP 0xd503201f+#define ORN 0xaa200000+#define ORR 0xaa000000+#define ORRI 0xb2000000+#define RET 0xd65f0000+#define SBC 0xda000000+#define SBFM 0x93000000+#define SCVTF 0x9e620000+#define SDIV 0x9ac00c00+#define SMADDL 0x9b200000+#define SMULH 0x9b403c00+#define STP 0xa9000000+#define STP_PRE 0xa9800000+#define STRB 0x38206800+#define STRBI 0x39000000+#define STRI 0xf9000000+#define STR_FI 0x3d000000+#define STR_FR 0x3c206800+#define STUR_FI 0x3c000000+#define STURBI 0x38000000+#define SUB 0xcb000000+#define SUBI 0xd1000000+#define SUBS 0xeb000000+#define UBFM 0xd3000000+#define UDIV 0x9ac00800+#define UMULH 0x9bc03c00++/* dest_reg is the absolute name of the register+ Useful for reordering instructions in the delay slot. */+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)+{+ sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ *ptr = ins;+ compiler->size++;+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_imm64_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)+{+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5)));+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 16) & 0xffff) << 5) | (1 << 21)));+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 32) & 0xffff) << 5) | (2 << 21)));+ return push_inst(compiler, MOVK | RD(dst) | ((imm >> 48) << 5) | (3 << 21));+}++static SLJIT_INLINE sljit_sw detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_sw diff;+ sljit_uw target_addr;++ if (jump->flags & SLJIT_REWRITABLE_JUMP) {+ jump->flags |= PATCH_ABS64;+ return 0;+ }++ if (jump->flags & JUMP_ADDR)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;+ }++ diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4) - executable_offset;++ if (jump->flags & IS_COND) {+ diff += sizeof(sljit_ins);+ if (diff <= 0xfffff && diff >= -0x100000) {+ code_ptr[-5] ^= (jump->flags & IS_CBZ) ? (0x1 << 24) : 0x1;+ jump->addr -= sizeof(sljit_ins);+ jump->flags |= PATCH_COND;+ return 5;+ }+ diff -= sizeof(sljit_ins);+ }++ if (diff <= 0x7ffffff && diff >= -0x8000000) {+ jump->flags |= PATCH_B;+ return 4;+ }++ if (target_addr < 0x100000000l) {+ if (jump->flags & IS_COND)+ code_ptr[-5] -= (2 << 5);+ code_ptr[-2] = code_ptr[0];+ return 2;+ }++ if (target_addr < 0x1000000000000l) {+ if (jump->flags & IS_COND)+ code_ptr[-5] -= (1 << 5);+ jump->flags |= PATCH_ABS48;+ code_ptr[-1] = code_ptr[0];+ return 1;+ }++ jump->flags |= PATCH_ABS64;+ return 0;+}++static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)+{+ if (max_label < 0x100000000l) {+ put_label->flags = 0;+ return 2;+ }++ if (max_label < 0x1000000000000l) {+ put_label->flags = 1;+ return 1;+ }++ put_label->flags = 2;+ return 0;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ sljit_uw next_addr;+ sljit_sw executable_offset;+ sljit_uw addr;+ sljit_s32 dst;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ struct sljit_put_label *put_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));+ reverse_buf(compiler);++ code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);+ PTR_FAIL_WITH_EXEC_IF(code);+ buf = compiler->buf;++ code_ptr = code;+ word_count = 0;+ next_addr = 0;+ executable_offset = SLJIT_EXEC_OFFSET(code);++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ put_label = compiler->put_labels;++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+ *code_ptr = *buf_ptr++;+ if (next_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);++ /* These structures are ordered by their address. */+ if (label && label->size == word_count) {+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = code_ptr - code;+ label = label->next;+ }+ if (jump && jump->addr == word_count) {+ jump->addr = (sljit_uw)(code_ptr - 4);+ code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);+ jump = jump->next;+ }+ if (const_ && const_->addr == word_count) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ }+ if (put_label && put_label->addr == word_count) {+ SLJIT_ASSERT(put_label->label);+ put_label->addr = (sljit_uw)(code_ptr - 3);+ code_ptr -= put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));+ put_label = put_label->next;+ }+ next_addr = compute_next_addr(label, jump, const_, put_label);+ }+ code_ptr ++;+ word_count ++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = code_ptr - code;+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(!put_label);+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);++ jump = compiler->jumps;+ while (jump) {+ do {+ addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;+ buf_ptr = (sljit_ins *)jump->addr;++ if (jump->flags & PATCH_B) {+ addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;+ SLJIT_ASSERT((sljit_sw)addr <= 0x1ffffff && (sljit_sw)addr >= -0x2000000);+ buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (addr & 0x3ffffff);+ if (jump->flags & IS_COND)+ buf_ptr[-1] -= (4 << 5);+ break;+ }+ if (jump->flags & PATCH_COND) {+ addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;+ SLJIT_ASSERT((sljit_sw)addr <= 0x3ffff && (sljit_sw)addr >= -0x40000);+ buf_ptr[0] = (buf_ptr[0] & ~0xffffe0) | ((addr & 0x7ffff) << 5);+ break;+ }++ SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || addr <= 0xffffffffl);+ SLJIT_ASSERT((jump->flags & PATCH_ABS64) || addr <= 0xffffffffffffl);++ dst = buf_ptr[0] & 0x1f;+ buf_ptr[0] = MOVZ | dst | ((addr & 0xffff) << 5);+ buf_ptr[1] = MOVK | dst | (((addr >> 16) & 0xffff) << 5) | (1 << 21);+ if (jump->flags & (PATCH_ABS48 | PATCH_ABS64))+ buf_ptr[2] = MOVK | dst | (((addr >> 32) & 0xffff) << 5) | (2 << 21);+ if (jump->flags & PATCH_ABS64)+ buf_ptr[3] = MOVK | dst | (((addr >> 48) & 0xffff) << 5) | (3 << 21);+ } while (0);+ jump = jump->next;+ }++ put_label = compiler->put_labels;+ while (put_label) {+ addr = put_label->label->addr;+ buf_ptr = (sljit_ins *)put_label->addr;++ buf_ptr[0] |= (addr & 0xffff) << 5;+ buf_ptr[1] |= ((addr >> 16) & 0xffff) << 5;++ if (put_label->flags >= 1)+ buf_ptr[2] |= ((addr >> 32) & 0xffff) << 5;++ if (put_label->flags >= 2)+ buf_ptr[3] |= ((addr >> 48) & 0xffff) << 5;++ put_label = put_label->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);++ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ SLJIT_CACHE_FLUSH(code, code_ptr);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ return code;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ switch (feature_type) {+ case SLJIT_HAS_FPU:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return SLJIT_IS_FPU_AVAILABLE;+#else+ /* Available by default. */+ return 1;+#endif++ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_CMOV:+ case SLJIT_HAS_PREFETCH:+ return 1;++ default:+ return 0;+ }+}++/* --------------------------------------------------------------------- */+/* Core code generator functions. */+/* --------------------------------------------------------------------- */++#define COUNT_TRAILING_ZERO(value, result) \+ result = 0; \+ if (!(value & 0xffffffff)) { \+ result += 32; \+ value >>= 32; \+ } \+ if (!(value & 0xffff)) { \+ result += 16; \+ value >>= 16; \+ } \+ if (!(value & 0xff)) { \+ result += 8; \+ value >>= 8; \+ } \+ if (!(value & 0xf)) { \+ result += 4; \+ value >>= 4; \+ } \+ if (!(value & 0x3)) { \+ result += 2; \+ value >>= 2; \+ } \+ if (!(value & 0x1)) { \+ result += 1; \+ value >>= 1; \+ }++#define LOGICAL_IMM_CHECK 0x100++static sljit_ins logical_imm(sljit_sw imm, sljit_s32 len)+{+ sljit_s32 negated, ones, right;+ sljit_uw mask, uimm;+ sljit_ins ins;++ if (len & LOGICAL_IMM_CHECK) {+ len &= ~LOGICAL_IMM_CHECK;+ if (len == 32 && (imm == 0 || imm == -1))+ return 0;+ if (len == 16 && ((sljit_s32)imm == 0 || (sljit_s32)imm == -1))+ return 0;+ }++ SLJIT_ASSERT((len == 32 && imm != 0 && imm != -1)+ || (len == 16 && (sljit_s32)imm != 0 && (sljit_s32)imm != -1));++ uimm = (sljit_uw)imm;+ while (1) {+ if (len <= 0) {+ SLJIT_UNREACHABLE();+ return 0;+ }++ mask = ((sljit_uw)1 << len) - 1;+ if ((uimm & mask) != ((uimm >> len) & mask))+ break;+ len >>= 1;+ }++ len <<= 1;++ negated = 0;+ if (uimm & 0x1) {+ negated = 1;+ uimm = ~uimm;+ }++ if (len < 64)+ uimm &= ((sljit_uw)1 << len) - 1;++ /* Unsigned right shift. */+ COUNT_TRAILING_ZERO(uimm, right);++ /* Signed shift. We also know that the highest bit is set. */+ imm = (sljit_sw)~uimm;+ SLJIT_ASSERT(imm < 0);++ COUNT_TRAILING_ZERO(imm, ones);++ if (~imm)+ return 0;++ if (len == 64)+ ins = 1 << 22;+ else+ ins = (0x3f - ((len << 1) - 1)) << 10;++ if (negated)+ return ins | ((len - ones - 1) << 10) | ((len - ones - right) << 16);++ return ins | ((ones - 1) << 10) | ((len - right) << 16);+}++#undef COUNT_TRAILING_ZERO++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw simm)+{+ sljit_uw imm = (sljit_uw)simm;+ sljit_s32 i, zeros, ones, first;+ sljit_ins bitmask;++ /* Handling simple immediates first. */+ if (imm <= 0xffff)+ return push_inst(compiler, MOVZ | RD(dst) | (imm << 5));++ if (simm < 0 && simm >= -0x10000)+ return push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5));++ if (imm <= 0xffffffffl) {+ if ((imm & 0xffff) == 0)+ return push_inst(compiler, MOVZ | RD(dst) | ((imm >> 16) << 5) | (1 << 21));+ if ((imm & 0xffff0000l) == 0xffff0000)+ return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff) << 5));+ if ((imm & 0xffff) == 0xffff)+ return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));++ bitmask = logical_imm(simm, 16);+ if (bitmask != 0)+ return push_inst(compiler, (ORRI ^ W_OP) | RD(dst) | RN(TMP_ZERO) | bitmask);++ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5)));+ return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));+ }++ bitmask = logical_imm(simm, 32);+ if (bitmask != 0)+ return push_inst(compiler, ORRI | RD(dst) | RN(TMP_ZERO) | bitmask);++ if (simm < 0 && simm >= -0x100000000l) {+ if ((imm & 0xffff) == 0xffff)+ return push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));++ FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5)));+ return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));+ }++ /* A large amount of number can be constructed from ORR and MOVx, but computing them is costly. */++ zeros = 0;+ ones = 0;+ for (i = 4; i > 0; i--) {+ if ((simm & 0xffff) == 0)+ zeros++;+ if ((simm & 0xffff) == 0xffff)+ ones++;+ simm >>= 16;+ }++ simm = (sljit_sw)imm;+ first = 1;+ if (ones > zeros) {+ simm = ~simm;+ for (i = 0; i < 4; i++) {+ if (!(simm & 0xffff)) {+ simm >>= 16;+ continue;+ }+ if (first) {+ first = 0;+ FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((simm & 0xffff) << 5) | (i << 21)));+ }+ else+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | ((~simm & 0xffff) << 5) | (i << 21)));+ simm >>= 16;+ }+ return SLJIT_SUCCESS;+ }++ for (i = 0; i < 4; i++) {+ if (!(simm & 0xffff)) {+ simm >>= 16;+ continue;+ }+ if (first) {+ first = 0;+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((simm & 0xffff) << 5) | (i << 21)));+ }+ else+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | ((simm & 0xffff) << 5) | (i << 21)));+ simm >>= 16;+ }+ return SLJIT_SUCCESS;+}++#define ARG1_IMM 0x0010000+#define ARG2_IMM 0x0020000+#define INT_OP 0x0040000+#define SET_FLAGS 0x0080000+#define UNUSED_RETURN 0x0100000++#define CHECK_FLAGS(flag_bits) \+ if (flags & SET_FLAGS) { \+ inv_bits |= flag_bits; \+ if (flags & UNUSED_RETURN) \+ dst = TMP_ZERO; \+ }++static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 dst, sljit_sw arg1, sljit_sw arg2)+{+ /* dst must be register, TMP_REG1+ arg1 must be register, TMP_REG1, imm+ arg2 must be register, TMP_REG2, imm */+ sljit_ins inv_bits = (flags & INT_OP) ? W_OP : 0;+ sljit_ins inst_bits;+ sljit_s32 op = (flags & 0xffff);+ sljit_s32 reg;+ sljit_sw imm, nimm;++ if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {+ /* Both are immediates. */+ flags &= ~ARG1_IMM;+ if (arg1 == 0 && op != SLJIT_ADD && op != SLJIT_SUB)+ arg1 = TMP_ZERO;+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));+ arg1 = TMP_REG1;+ }+ }++ if (flags & (ARG1_IMM | ARG2_IMM)) {+ reg = (flags & ARG2_IMM) ? arg1 : arg2;+ imm = (flags & ARG2_IMM) ? arg2 : arg1;++ switch (op) {+ case SLJIT_MUL:+ case SLJIT_NEG:+ case SLJIT_CLZ:+ case SLJIT_ADDC:+ case SLJIT_SUBC:+ /* No form with immediate operand (except imm 0, which+ is represented by a ZERO register). */+ break;+ case SLJIT_MOV:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1);+ return load_immediate(compiler, dst, imm);+ case SLJIT_NOT:+ SLJIT_ASSERT(flags & ARG2_IMM);+ FAIL_IF(load_immediate(compiler, dst, (flags & INT_OP) ? (~imm & 0xffffffff) : ~imm));+ goto set_flags;+ case SLJIT_SUB:+ if (flags & ARG1_IMM)+ break;+ imm = -imm;+ /* Fall through. */+ case SLJIT_ADD:+ if (imm == 0) {+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, ((op == SLJIT_ADD ? ADDI : SUBI) ^ inv_bits) | RD(dst) | RN(reg));+ }+ if (imm > 0 && imm <= 0xfff) {+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (imm << 10));+ }+ nimm = -imm;+ if (nimm > 0 && nimm <= 0xfff) {+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (nimm << 10));+ }+ if (imm > 0 && imm <= 0xffffff && !(imm & 0xfff)) {+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((imm >> 12) << 10) | (1 << 22));+ }+ if (nimm > 0 && nimm <= 0xffffff && !(nimm & 0xfff)) {+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((nimm >> 12) << 10) | (1 << 22));+ }+ if (imm > 0 && imm <= 0xffffff && !(flags & SET_FLAGS)) {+ FAIL_IF(push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((imm >> 12) << 10) | (1 << 22)));+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(dst) | ((imm & 0xfff) << 10));+ }+ if (nimm > 0 && nimm <= 0xffffff && !(flags & SET_FLAGS)) {+ FAIL_IF(push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((nimm >> 12) << 10) | (1 << 22)));+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(dst) | ((nimm & 0xfff) << 10));+ }+ break;+ case SLJIT_AND:+ inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));+ if (!inst_bits)+ break;+ CHECK_FLAGS(3 << 29);+ return push_inst(compiler, (ANDI ^ inv_bits) | RD(dst) | RN(reg) | inst_bits);+ case SLJIT_OR:+ case SLJIT_XOR:+ inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));+ if (!inst_bits)+ break;+ if (op == SLJIT_OR)+ inst_bits |= ORRI;+ else+ inst_bits |= EORI;+ FAIL_IF(push_inst(compiler, (inst_bits ^ inv_bits) | RD(dst) | RN(reg)));+ goto set_flags;+ case SLJIT_SHL:+ if (flags & ARG1_IMM)+ break;+ if (flags & INT_OP) {+ imm &= 0x1f;+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | ((-imm & 0x1f) << 16) | ((31 - imm) << 10)));+ }+ else {+ imm &= 0x3f;+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) | ((-imm & 0x3f) << 16) | ((63 - imm) << 10)));+ }+ goto set_flags;+ case SLJIT_LSHR:+ case SLJIT_ASHR:+ if (flags & ARG1_IMM)+ break;+ if (op == SLJIT_ASHR)+ inv_bits |= 1 << 30;+ if (flags & INT_OP) {+ imm &= 0x1f;+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (imm << 16) | (31 << 10)));+ }+ else {+ imm &= 0x3f;+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) | (imm << 16) | (63 << 10)));+ }+ goto set_flags;+ default:+ SLJIT_UNREACHABLE();+ break;+ }++ if (flags & ARG2_IMM) {+ if (arg2 == 0)+ arg2 = TMP_ZERO;+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG2, arg2));+ arg2 = TMP_REG2;+ }+ }+ else {+ if (arg1 == 0)+ arg1 = TMP_ZERO;+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));+ arg1 = TMP_REG1;+ }+ }+ }++ /* Both arguments are registers. */+ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ if (dst == arg2)+ return SLJIT_SUCCESS;+ return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(arg2));+ case SLJIT_MOV_U8:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ return push_inst(compiler, (UBFM ^ W_OP) | RD(dst) | RN(arg2) | (7 << 10));+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ if (!(flags & INT_OP))+ inv_bits |= 1 << 22;+ return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10));+ case SLJIT_MOV_U16:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ return push_inst(compiler, (UBFM ^ W_OP) | RD(dst) | RN(arg2) | (15 << 10));+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ if (!(flags & INT_OP))+ inv_bits |= 1 << 22;+ return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10));+ case SLJIT_MOV_U32:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ if ((flags & INT_OP) && dst == arg2)+ return SLJIT_SUCCESS;+ return push_inst(compiler, (ORR ^ W_OP) | RD(dst) | RN(TMP_ZERO) | RM(arg2));+ case SLJIT_MOV_S32:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);+ if ((flags & INT_OP) && dst == arg2)+ return SLJIT_SUCCESS;+ return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(arg2) | (31 << 10));+ case SLJIT_NOT:+ SLJIT_ASSERT(arg1 == TMP_REG1);+ FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)));+ break; /* Set flags. */+ case SLJIT_NEG:+ SLJIT_ASSERT(arg1 == TMP_REG1);+ if (flags & SET_FLAGS)+ inv_bits |= 1 << 29;+ return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2));+ case SLJIT_CLZ:+ SLJIT_ASSERT(arg1 == TMP_REG1);+ return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2));+ case SLJIT_ADD:+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));+ case SLJIT_ADDC:+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (ADC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));+ case SLJIT_SUB:+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));+ case SLJIT_SUBC:+ CHECK_FLAGS(1 << 29);+ return push_inst(compiler, (SBC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));+ case SLJIT_MUL:+ if (!(flags & SET_FLAGS))+ return push_inst(compiler, (MADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO));+ if (flags & INT_OP) {+ FAIL_IF(push_inst(compiler, SMADDL | RD(dst) | RN(arg1) | RM(arg2) | (31 << 10)));+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_LR) | RN(TMP_ZERO) | RM(dst) | (2 << 22) | (31 << 10)));+ return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_LR) | RM(dst) | (2 << 22) | (63 << 10));+ }+ FAIL_IF(push_inst(compiler, SMULH | RD(TMP_LR) | RN(arg1) | RM(arg2)));+ FAIL_IF(push_inst(compiler, MADD | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO)));+ return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_LR) | RM(dst) | (2 << 22) | (63 << 10));+ case SLJIT_AND:+ CHECK_FLAGS(3 << 29);+ return push_inst(compiler, (AND ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));+ case SLJIT_OR:+ FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));+ break; /* Set flags. */+ case SLJIT_XOR:+ FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));+ break; /* Set flags. */+ case SLJIT_SHL:+ FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));+ break; /* Set flags. */+ case SLJIT_LSHR:+ FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));+ break; /* Set flags. */+ case SLJIT_ASHR:+ FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));+ break; /* Set flags. */+ default:+ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+ }++set_flags:+ if (flags & SET_FLAGS)+ return push_inst(compiler, (SUBS ^ inv_bits) | RD(TMP_ZERO) | RN(dst) | RM(TMP_ZERO));+ return SLJIT_SUCCESS;+}++#define STORE 0x10+#define SIGNED 0x20++#define BYTE_SIZE 0x0+#define HALF_SIZE 0x1+#define INT_SIZE 0x2+#define WORD_SIZE 0x3++#define MEM_SIZE_SHIFT(flags) ((flags) & 0x3)++static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)+{+ sljit_u32 shift = MEM_SIZE_SHIFT(flags);+ sljit_u32 type = (shift << 30);++ if (!(flags & STORE))+ type |= (flags & SIGNED) ? 0x00800000 : 0x00400000;++ SLJIT_ASSERT(arg & SLJIT_MEM);++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ if (argw == 0 || argw == shift)+ return push_inst(compiler, STRB | type | RT(reg)+ | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));++ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw << 10)));+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg));+ }++ arg &= REG_MASK;++ if (arg == SLJIT_UNUSED) {+ FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~(0xfff << shift)));++ argw = (argw >> shift) & 0xfff;++ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | (argw << 10));+ }++ if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) {+ if ((argw >> shift) <= 0xfff) {+ return push_inst(compiler, STRBI | type | RT(reg) | RN(arg) | (argw << (10 - shift)));+ }++ if (argw <= 0xffffff) {+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | ((argw >> 12) << 10)));++ argw = ((argw & 0xfff) >> shift);+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | (argw << 10));+ }+ }++ if (argw <= 255 && argw >= -256)+ return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | ((argw & 0x1ff) << 12));++ FAIL_IF(load_immediate(compiler, tmp_reg, argw));++ return push_inst(compiler, STRB | type | RT(reg) | RN(arg) | RM(tmp_reg));+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 args, i, tmp, offs, prev, saved_regs_size;++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);+ if (saved_regs_size & 0x8)+ saved_regs_size += sizeof(sljit_sw);++ local_size = (local_size + 15) & ~0xf;+ compiler->local_size = local_size + saved_regs_size;++ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)+ | RN(SLJIT_SP) | ((-(saved_regs_size >> 3) & 0x7f) << 15)));++#ifdef _WIN32+ if (local_size >= 4096)+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));+ else if (local_size > 256)+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(SLJIT_SP) | (local_size << 10)));+#endif++ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;+ prev = -1;+ offs = 2 << 15;+ for (i = SLJIT_S0; i >= tmp; i--) {+ if (prev == -1) {+ prev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));+ offs += 2 << 15;+ prev = -1;+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ if (prev == -1) {+ prev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));+ offs += 2 << 15;+ prev = -1;+ }++ if (prev != -1)+ FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5)));+++ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_FP) | RN(SLJIT_SP) | (0 << 10)));++ args = get_arg_count(arg_types);++ if (args >= 1)+ FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0) | RN(TMP_ZERO) | RM(SLJIT_R0)));+ if (args >= 2)+ FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S1) | RN(TMP_ZERO) | RM(SLJIT_R1)));+ if (args >= 3)+ FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S2) | RN(TMP_ZERO) | RM(SLJIT_R2)));++#ifdef _WIN32+ if (local_size >= 4096) {+ if (local_size < 4 * 4096) {+ /* No need for a loop. */+ if (local_size >= 2 * 4096) {+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22)));+ local_size -= 4096;+ }++ if (local_size >= 2 * 4096) {+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22)));+ local_size -= 4096;+ }++ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));+ local_size -= 4096;+ }+ else {+ FAIL_IF(push_inst(compiler, MOVZ | RD(TMP_REG2) | (((local_size >> 12) - 1) << 5)));+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22)));+ FAIL_IF(push_inst(compiler, SUBI | (1 << 29) | RD(TMP_REG2) | RN(TMP_REG2) | (1 << 10)));+ FAIL_IF(push_inst(compiler, B_CC | ((((sljit_ins) -3) & 0x7ffff) << 5) | 0x1 /* not-equal */));+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));++ local_size &= 0xfff;+ }++ if (local_size > 256) {+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (local_size << 10)));+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));+ }+ else if (local_size > 0)+ FAIL_IF(push_inst(compiler, LDR_PRE | RT(TMP_ZERO) | RN(TMP_REG1) | ((-local_size & 0x1ff) << 12)));++ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_REG1) | (0 << 10)));+ }+ else if (local_size > 256) {+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_REG1) | (0 << 10)));+ }+ else if (local_size > 0)+ FAIL_IF(push_inst(compiler, LDR_PRE | RT(TMP_ZERO) | RN(SLJIT_SP) | ((-local_size & 0x1ff) << 12)));++#else /* !_WIN32 */++ /* The local_size does not include saved registers size. */+ if (local_size > 0xfff) {+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((local_size >> 12) << 10) | (1 << 22)));+ local_size &= 0xfff;+ }+ if (local_size != 0)+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (local_size << 10)));++#endif /* _WIN32 */++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 saved_regs_size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);+ if (saved_regs_size & 0x8)+ saved_regs_size += sizeof(sljit_sw);++ compiler->local_size = saved_regs_size + ((local_size + 15) & ~0xf);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 local_size;+ sljit_s32 i, tmp, offs, prev, saved_regs_size;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));++ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));++ saved_regs_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 2);+ if (saved_regs_size & 0x8)+ saved_regs_size += sizeof(sljit_sw);++ local_size = compiler->local_size - saved_regs_size;++ /* Load LR as early as possible. */+ if (local_size == 0)+ FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));+ else if (local_size < 63 * sizeof(sljit_sw)) {+ FAIL_IF(push_inst(compiler, LDP_PRE | RT(TMP_FP) | RT2(TMP_LR)+ | RN(SLJIT_SP) | (local_size << (15 - 3))));+ }+ else {+ if (local_size > 0xfff) {+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((local_size >> 12) << 10) | (1 << 22)));+ local_size &= 0xfff;+ }+ if (local_size)+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (local_size << 10)));++ FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));+ }++ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;+ prev = -1;+ offs = 2 << 15;+ for (i = SLJIT_S0; i >= tmp; i--) {+ if (prev == -1) {+ prev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));+ offs += 2 << 15;+ prev = -1;+ }++ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ if (prev == -1) {+ prev = i;+ continue;+ }+ FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));+ offs += 2 << 15;+ prev = -1;+ }++ if (prev != -1)+ FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5)));++ /* These two can be executed in parallel. */+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (saved_regs_size << 10)));+ return push_inst(compiler, RET | RN(TMP_LR));+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+ sljit_ins inv_bits = (op & SLJIT_I32_OP) ? W_OP : 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ return push_inst(compiler, BRK);+ case SLJIT_NOP:+ return push_inst(compiler, NOP);+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+ FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));+ FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));+ return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIVMOD_SW:+ FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));+ FAIL_IF(push_inst(compiler, ((op == SLJIT_DIVMOD_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)));+ FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));+ return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));+ case SLJIT_DIV_UW:+ case SLJIT_DIV_SW:+ return push_inst(compiler, ((op == SLJIT_DIV_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1));+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r, flags, mem_flags;+ sljit_s32 op_flags = GET_ALL_FLAGS(op);++ CHECK_ERROR();+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;++ op = GET_OPCODE(op);+ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {+ /* Both operands are registers. */+ if (dst_r != TMP_REG1 && FAST_IS_REG(src))+ return emit_op_imm(compiler, op | ((op_flags & SLJIT_I32_OP) ? INT_OP : 0), dst_r, TMP_REG1, src);++ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ mem_flags = WORD_SIZE;+ break;+ case SLJIT_MOV_U8:+ mem_flags = BYTE_SIZE;+ if (src & SLJIT_IMM)+ srcw = (sljit_u8)srcw;+ break;+ case SLJIT_MOV_S8:+ mem_flags = BYTE_SIZE | SIGNED;+ if (src & SLJIT_IMM)+ srcw = (sljit_s8)srcw;+ break;+ case SLJIT_MOV_U16:+ mem_flags = HALF_SIZE;+ if (src & SLJIT_IMM)+ srcw = (sljit_u16)srcw;+ break;+ case SLJIT_MOV_S16:+ mem_flags = HALF_SIZE | SIGNED;+ if (src & SLJIT_IMM)+ srcw = (sljit_s16)srcw;+ break;+ case SLJIT_MOV_U32:+ mem_flags = INT_SIZE;+ if (src & SLJIT_IMM)+ srcw = (sljit_u32)srcw;+ break;+ case SLJIT_MOV_S32:+ mem_flags = INT_SIZE | SIGNED;+ if (src & SLJIT_IMM)+ srcw = (sljit_s32)srcw;+ break;+ default:+ SLJIT_UNREACHABLE();+ mem_flags = 0;+ break;+ }++ if (src & SLJIT_IMM)+ FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw));+ else if (!(src & SLJIT_MEM))+ dst_r = src;+ else+ FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, src, srcw, TMP_REG1));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+ }++ flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;+ mem_flags = WORD_SIZE;++ if (op_flags & SLJIT_I32_OP) {+ flags |= INT_OP;+ mem_flags = INT_SIZE;+ }++ if (dst == SLJIT_UNUSED)+ flags |= UNUSED_RETURN;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src, srcw, TMP_REG2));+ src = TMP_REG2;+ }++ emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, src);++ if (SLJIT_UNLIKELY(dst & SLJIT_MEM))+ return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 dst_r, flags, mem_flags;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))+ return SLJIT_SUCCESS;++ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;+ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;+ mem_flags = WORD_SIZE;++ if (op & SLJIT_I32_OP) {+ flags |= INT_OP;+ mem_flags = INT_SIZE;+ }++ if (dst == SLJIT_UNUSED)+ flags |= UNUSED_RETURN;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, src1, src1w, TMP_REG1));+ src1 = TMP_REG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src2, src2w, TMP_REG2));+ src2 = TMP_REG2;+ }++ if (src1 & SLJIT_IMM)+ flags |= ARG1_IMM;+ else+ src1w = src1;++ if (src2 & SLJIT_IMM)+ flags |= ARG2_IMM;+ else+ src2w = src2;++ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w);++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src)));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1));++ return push_inst(compiler, RET | RN(TMP_LR));+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4);++ /* The reg_map[op] should provide the appropriate constant. */+ if (op == SLJIT_PREFETCH_L1)+ op = 1;+ else if (op == SLJIT_PREFETCH_L2)+ op = 3;+ else if (op == SLJIT_PREFETCH_L3)+ op = 5;+ else+ op = 2;++ /* Signed word sized load is the prefetch instruction. */+ return emit_op_mem(compiler, WORD_SIZE | SIGNED, op, src, srcw, TMP_REG1);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(reg));+ return reg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));+ return freg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_ins*)instruction);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ sljit_u32 shift = MEM_SIZE_SHIFT(flags);+ sljit_ins type = (shift << 30);++ SLJIT_ASSERT(arg & SLJIT_MEM);++ if (!(flags & STORE))+ type |= 0x00400000;++ if (arg & OFFS_REG_MASK) {+ argw &= 3;+ if (argw == 0 || argw == shift)+ return push_inst(compiler, STR_FR | type | VT(reg)+ | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));++ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw << 10)));+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1));+ }++ arg &= REG_MASK;++ if (arg == SLJIT_UNUSED) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, argw & ~(0xfff << shift)));++ argw = (argw >> shift) & 0xfff;++ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | (argw << 10));+ }++ if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) {+ if ((argw >> shift) <= 0xfff)+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(arg) | (argw << (10 - shift)));++ if (argw <= 0xffffff) {+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(TMP_REG1) | RN(arg) | ((argw >> 12) << 10)));++ argw = ((argw & 0xfff) >> shift);+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | (argw << 10));+ }+ }++ if (argw <= 255 && argw >= -256)+ return push_inst(compiler, STUR_FI | type | VT(reg) | RN(arg) | ((argw & 0x1ff) << 12));++ FAIL_IF(load_immediate(compiler, TMP_REG1, argw));+ return push_inst(compiler, STR_FR | type | VT(reg) | RN(arg) | RM(TMP_REG1));+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;++ if (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64)+ inv_bits |= W_OP;++ if (src & SLJIT_MEM) {+ emit_fop_mem(compiler, (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw);+ src = TMP_FREG1;+ }++ FAIL_IF(push_inst(compiler, (FCVTZS ^ inv_bits) | RD(dst_r) | VN(src)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;+ sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)+ inv_bits |= W_OP;++ if (src & SLJIT_MEM) {+ emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw, TMP_REG1);+ src = TMP_REG1;+ } else if (src & SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)+ srcw = (sljit_s32)srcw;+#endif+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, (SCVTF ^ inv_bits) | VD(dst_r) | RN(src)));++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, ((op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE) | STORE, TMP_FREG1, dst, dstw);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE;+ sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;++ if (src1 & SLJIT_MEM) {+ emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w);+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w);+ src2 = TMP_FREG2;+ }++ return push_inst(compiler, (FCMP ^ inv_bits) | VN(src1) | VM(src2));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r, mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE;+ sljit_ins inv_bits;++ CHECK_ERROR();++ SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x1) == WORD_SIZE, must_be_one_bit_difference);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) ? (mem_flags ^ 0x1) : mem_flags, dst_r, src, srcw);+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (dst_r != TMP_FREG1)+ FAIL_IF(push_inst(compiler, (FMOV ^ inv_bits) | VD(dst_r) | VN(src)));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(src)));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src)));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ FAIL_IF(push_inst(compiler, FCVT | ((op & SLJIT_F32_OP) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src)));+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, mem_flags | STORE, dst_r, dst, dstw);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 dst_r, mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE;+ sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;+ if (src1 & SLJIT_MEM) {+ emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w);+ src1 = TMP_FREG1;+ }+ if (src2 & SLJIT_MEM) {+ emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w);+ src2 = TMP_FREG2;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst(compiler, (FADD ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));+ break;+ case SLJIT_SUB_F64:+ FAIL_IF(push_inst(compiler, (FSUB ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));+ break;+ case SLJIT_MUL_F64:+ FAIL_IF(push_inst(compiler, (FMUL ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));+ break;+ case SLJIT_DIV_F64:+ FAIL_IF(push_inst(compiler, (FDIV ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));+ break;+ }++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;+ return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw);+}++/* --------------------------------------------------------------------- */+/* Other instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ if (FAST_IS_REG(dst))+ return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR));++ /* Memory. */+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw, TMP_REG1);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++static sljit_uw get_cc(sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_MUL_NOT_OVERFLOW:+ case SLJIT_EQUAL_F64:+ return 0x1;++ case SLJIT_NOT_EQUAL:+ case SLJIT_MUL_OVERFLOW:+ case SLJIT_NOT_EQUAL_F64:+ return 0x0;++ case SLJIT_LESS:+ case SLJIT_LESS_F64:+ return 0x2;++ case SLJIT_GREATER_EQUAL:+ case SLJIT_GREATER_EQUAL_F64:+ return 0x3;++ case SLJIT_GREATER:+ case SLJIT_GREATER_F64:+ return 0x9;++ case SLJIT_LESS_EQUAL:+ case SLJIT_LESS_EQUAL_F64:+ return 0x8;++ case SLJIT_SIG_LESS:+ return 0xa;++ case SLJIT_SIG_GREATER_EQUAL:+ return 0xb;++ case SLJIT_SIG_GREATER:+ return 0xd;++ case SLJIT_SIG_LESS_EQUAL:+ return 0xc;++ case SLJIT_OVERFLOW:+ case SLJIT_UNORDERED_F64:+ return 0x7;++ case SLJIT_NOT_OVERFLOW:+ case SLJIT_ORDERED_F64:+ return 0x6;++ default:+ SLJIT_UNREACHABLE();+ return 0xe;+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ if (type < SLJIT_JUMP) {+ jump->flags |= IS_COND;+ PTR_FAIL_IF(push_inst(compiler, B_CC | (6 << 5) | get_cc(type)));+ }+ else if (type >= SLJIT_FAST_CALL)+ jump->flags |= IS_BL;++ PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0));+ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1)));++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_jump(compiler, type);+}++static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src, sljit_sw srcw)+{+ struct sljit_jump *jump;+ sljit_ins inv_bits = (type & SLJIT_I32_OP) ? W_OP : 0;++ SLJIT_ASSERT((type & 0xff) == SLJIT_EQUAL || (type & 0xff) == SLJIT_NOT_EQUAL);+ ADJUST_LOCAL_OFFSET(src, srcw);++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ jump->flags |= IS_CBZ | IS_COND;++ if (src & SLJIT_MEM) {+ PTR_FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }+ else if (src & SLJIT_IMM) {+ PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ }++ SLJIT_ASSERT(FAST_IS_REG(src));++ if ((type & 0xff) == SLJIT_EQUAL)+ inv_bits |= 1 << 24;++ PTR_FAIL_IF(push_inst(compiler, (CBZ ^ inv_bits) | (6 << 5) | RT(src)));+ PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0));+ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, BR | RN(TMP_REG1)));+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ struct sljit_jump *jump;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ if (!(src & SLJIT_IMM)) {+ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }+ return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(src));+ }++ /* These jumps are converted to jump/call instructions when possible. */+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));+ jump->u.target = srcw;++ FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0));+ jump->addr = compiler->size;+ return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_ijump(compiler, type, src, srcw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 type)+{+ sljit_s32 dst_r, src_r, flags, mem_flags;+ sljit_ins cc;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ cc = get_cc(type & 0xff);+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (GET_OPCODE(op) < SLJIT_ADD) {+ FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(dst_r) | RN(TMP_ZERO) | RM(TMP_ZERO)));++ if (dst_r == TMP_REG1) {+ mem_flags = (GET_OPCODE(op) == SLJIT_MOV ? WORD_SIZE : INT_SIZE) | STORE;+ return emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG2);+ }++ return SLJIT_SUCCESS;+ }++ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;+ mem_flags = WORD_SIZE;++ if (op & SLJIT_I32_OP) {+ flags |= INT_OP;+ mem_flags = INT_SIZE;+ }++ src_r = dst;++ if (dst & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG1));+ src_r = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(TMP_ZERO)));+ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src_r, TMP_REG2);++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_ins inv_bits = (dst_reg & SLJIT_I32_OP) ? W_OP : 0;+ sljit_ins cc;++ CHECK_ERROR();+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));++ if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {+ if (dst_reg & SLJIT_I32_OP)+ srcw = (sljit_s32)srcw;+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ srcw = 0;+ }++ cc = get_cc(type & 0xff);+ dst_reg &= ~SLJIT_I32_OP;++ return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_u32 sign = 0, inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ switch (type & 0xff) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400;+ break;+ case SLJIT_MOV_S8:+ sign = 1;+ case SLJIT_MOV_U8:+ inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400;+ break;+ case SLJIT_MOV_S16:+ sign = 1;+ case SLJIT_MOV_U16:+ inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400;+ break;+ case SLJIT_MOV_S32:+ sign = 1;+ case SLJIT_MOV_U32:+ inst = STURBI | (MEM_SIZE_SHIFT(INT_SIZE) << 30) | 0x400;+ break;+ default:+ SLJIT_UNREACHABLE();+ inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400;+ break;+ }++ if (!(type & SLJIT_MEM_STORE))+ inst |= sign ? 0x00800000 : 0x00400000;++ if (type & SLJIT_MEM_PRE)+ inst |= 0x800;++ return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | ((memw & 0x1ff) << 12));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_u32 inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));++ if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ inst = STUR_FI | 0x80000400;++ if (!(type & SLJIT_F32_OP))+ inst |= 0x40000000;++ if (!(type & SLJIT_MEM_STORE))+ inst |= 0x00400000;++ if (type & SLJIT_MEM_PRE)+ inst |= 0x800;++ return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | ((memw & 0x1ff) << 12));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)+{+ sljit_s32 dst_reg;+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));++ SLJIT_ASSERT (SLJIT_LOCALS_OFFSET_BASE == 0);++ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (offset <= 0xffffff && offset >= -0xffffff) {+ ins = ADDI;+ if (offset < 0) {+ offset = -offset;+ ins = SUBI;+ }++ if (offset <= 0xfff)+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (offset << 10)));+ else {+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | ((offset & 0xfff000) >> (12 - 10)) | (1 << 22)));++ offset &= 0xfff;+ if (offset != 0)+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(dst_reg) | (offset << 10)));+ }+ }+ else {+ FAIL_IF(load_immediate (compiler, dst_reg, offset));+ /* Add extended register form. */+ FAIL_IF(push_inst(compiler, ADDE | (0x3 << 13) | RD(dst_reg) | RN(SLJIT_SP) | RM(dst_reg)));+ }++ if (SLJIT_UNLIKELY(dst & SLJIT_MEM))+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG1);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, init_value));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));+ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_put_label *put_label;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, 0));++ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));+ PTR_FAIL_IF(!put_label);+ set_put_label(put_label, compiler, 1);++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));++ return put_label;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ sljit_ins* inst = (sljit_ins*)addr;+ sljit_s32 dst;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);++ dst = inst[0] & 0x1f;+ SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21)));+ inst[0] = MOVZ | dst | ((new_target & 0xffff) << 5);+ inst[1] = MOVK | dst | (((new_target >> 16) & 0xffff) << 5) | (1 << 21);+ inst[2] = MOVK | dst | (((new_target >> 32) & 0xffff) << 5) | (2 << 21);+ inst[3] = MOVK | dst | ((new_target >> 48) << 5) | (3 << 21);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 4);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, new_constant, executable_offset);+}
+ src/c/pcre2/src/sljit/sljitNativeARM_T2_32.c view
@@ -0,0 +1,2383 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+#ifdef __SOFTFP__+ return "ARM-Thumb2" SLJIT_CPUINFO " ABI:softfp";+#else+ return "ARM-Thumb2" SLJIT_CPUINFO " ABI:hardfp";+#endif+}++/* Length of an instruction word. */+typedef sljit_u32 sljit_ins;++/* Last register + 1. */+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)+#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4)++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)++/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {+ 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15+};++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {+ 0, 0, 1, 2, 3, 4, 5, 6, 7+};++#define COPY_BITS(src, from, to, bits) \+ ((from >= to ? (src >> (from - to)) : (src << (to - from))) & (((1 << bits) - 1) << to))++/* Thumb16 encodings. */+#define RD3(rd) (reg_map[rd])+#define RN3(rn) (reg_map[rn] << 3)+#define RM3(rm) (reg_map[rm] << 6)+#define RDN3(rdn) (reg_map[rdn] << 8)+#define IMM3(imm) (imm << 6)+#define IMM8(imm) (imm)++/* Thumb16 helpers. */+#define SET_REGS44(rd, rn) \+ ((reg_map[rn] << 3) | (reg_map[rd] & 0x7) | ((reg_map[rd] & 0x8) << 4))+#define IS_2_LO_REGS(reg1, reg2) \+ (reg_map[reg1] <= 7 && reg_map[reg2] <= 7)+#define IS_3_LO_REGS(reg1, reg2, reg3) \+ (reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7)++/* Thumb32 encodings. */+#define RD4(rd) (reg_map[rd] << 8)+#define RN4(rn) (reg_map[rn] << 16)+#define RM4(rm) (reg_map[rm])+#define RT4(rt) (reg_map[rt] << 12)+#define DD4(dd) (freg_map[dd] << 12)+#define DN4(dn) (freg_map[dn] << 16)+#define DM4(dm) (freg_map[dm])+#define IMM5(imm) \+ (COPY_BITS(imm, 2, 12, 3) | ((imm & 0x3) << 6))+#define IMM12(imm) \+ (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++/* dot '.' changed to _+ I immediate form (possibly followed by number of immediate bits). */+#define ADCI 0xf1400000+#define ADCS 0x4140+#define ADC_W 0xeb400000+#define ADD 0x4400+#define ADDS 0x1800+#define ADDSI3 0x1c00+#define ADDSI8 0x3000+#define ADD_W 0xeb000000+#define ADDWI 0xf2000000+#define ADD_SP 0xb000+#define ADD_W 0xeb000000+#define ADD_WI 0xf1000000+#define ANDI 0xf0000000+#define ANDS 0x4000+#define AND_W 0xea000000+#define ASRS 0x4100+#define ASRSI 0x1000+#define ASR_W 0xfa40f000+#define ASR_WI 0xea4f0020+#define BCC 0xd000+#define BICI 0xf0200000+#define BKPT 0xbe00+#define BLX 0x4780+#define BX 0x4700+#define CLZ 0xfab0f080+#define CMNI_W 0xf1100f00+#define CMP 0x4280+#define CMPI 0x2800+#define CMPI_W 0xf1b00f00+#define CMP_X 0x4500+#define CMP_W 0xebb00f00+#define EORI 0xf0800000+#define EORS 0x4040+#define EOR_W 0xea800000+#define IT 0xbf00+#define LDRI 0xf8500800+#define LSLS 0x4080+#define LSLSI 0x0000+#define LSL_W 0xfa00f000+#define LSL_WI 0xea4f0000+#define LSRS 0x40c0+#define LSRSI 0x0800+#define LSR_W 0xfa20f000+#define LSR_WI 0xea4f0010+#define MOV 0x4600+#define MOVS 0x0000+#define MOVSI 0x2000+#define MOVT 0xf2c00000+#define MOVW 0xf2400000+#define MOV_W 0xea4f0000+#define MOV_WI 0xf04f0000+#define MUL 0xfb00f000+#define MVNS 0x43c0+#define MVN_W 0xea6f0000+#define MVN_WI 0xf06f0000+#define NOP 0xbf00+#define ORNI 0xf0600000+#define ORRI 0xf0400000+#define ORRS 0x4300+#define ORR_W 0xea400000+#define POP 0xbc00+#define POP_W 0xe8bd0000+#define PUSH 0xb400+#define PUSH_W 0xe92d0000+#define RSB_WI 0xf1c00000+#define RSBSI 0x4240+#define SBCI 0xf1600000+#define SBCS 0x4180+#define SBC_W 0xeb600000+#define SDIV 0xfb90f0f0+#define SMULL 0xfb800000+#define STR_SP 0x9000+#define SUBS 0x1a00+#define SUBSI3 0x1e00+#define SUBSI8 0x3800+#define SUB_W 0xeba00000+#define SUBWI 0xf2a00000+#define SUB_SP 0xb080+#define SUB_WI 0xf1a00000+#define SXTB 0xb240+#define SXTB_W 0xfa4ff080+#define SXTH 0xb200+#define SXTH_W 0xfa0ff080+#define TST 0x4200+#define UDIV 0xfbb0f0f0+#define UMULL 0xfba00000+#define UXTB 0xb2c0+#define UXTB_W 0xfa5ff080+#define UXTH 0xb280+#define UXTH_W 0xfa1ff080+#define VABS_F32 0xeeb00ac0+#define VADD_F32 0xee300a00+#define VCMP_F32 0xeeb40a40+#define VCVT_F32_S32 0xeeb80ac0+#define VCVT_F64_F32 0xeeb70ac0+#define VCVT_S32_F32 0xeebd0ac0+#define VDIV_F32 0xee800a00+#define VMOV_F32 0xeeb00a40+#define VMOV 0xee000a10+#define VMOV2 0xec400a10+#define VMRS 0xeef1fa10+#define VMUL_F32 0xee200a00+#define VNEG_F32 0xeeb10a40+#define VSTR_F32 0xed000a00+#define VSUB_F32 0xee300a40++static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_ins inst)+{+ sljit_u16 *ptr;+ SLJIT_ASSERT(!(inst & 0xffff0000));++ ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_u16));+ FAIL_IF(!ptr);+ *ptr = inst;+ compiler->size++;+ return SLJIT_SUCCESS;+}++static sljit_s32 push_inst32(struct sljit_compiler *compiler, sljit_ins inst)+{+ sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ *ptr++ = inst >> 16;+ *ptr = inst;+ compiler->size += 2;+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_imm32_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)+{+ FAIL_IF(push_inst32(compiler, MOVW | RD4(dst)+ | COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));+ return push_inst32(compiler, MOVT | RD4(dst)+ | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));+}++static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm)+{+ sljit_s32 dst = inst[1] & 0x0f00;+ SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00));+ inst[0] = (MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1);+ inst[1] = dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff);+ inst[2] = (MOVT >> 16) | COPY_BITS(new_imm, 12 + 16, 0, 4) | COPY_BITS(new_imm, 11 + 16, 10, 1);+ inst[3] = dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16);+}++static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)+{+ sljit_sw diff;++ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ return 0;++ if (jump->flags & JUMP_ADDR) {+ /* Branch to ARM code is not optimized yet. */+ if (!(jump->u.target & 0x1))+ return 0;+ diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset) >> 1;+ }+ else {+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);+ diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2)) >> 1;+ }++ if (jump->flags & IS_COND) {+ SLJIT_ASSERT(!(jump->flags & IS_BL));+ if (diff <= 127 && diff >= -128) {+ jump->flags |= PATCH_TYPE1;+ return 5;+ }+ if (diff <= 524287 && diff >= -524288) {+ jump->flags |= PATCH_TYPE2;+ return 4;+ }+ /* +1 comes from the prefix IT instruction. */+ diff--;+ if (diff <= 8388607 && diff >= -8388608) {+ jump->flags |= PATCH_TYPE3;+ return 3;+ }+ }+ else if (jump->flags & IS_BL) {+ if (diff <= 8388607 && diff >= -8388608) {+ jump->flags |= PATCH_BL;+ return 3;+ }+ }+ else {+ if (diff <= 1023 && diff >= -1024) {+ jump->flags |= PATCH_TYPE4;+ return 4;+ }+ if (diff <= 8388607 && diff >= -8388608) {+ jump->flags |= PATCH_TYPE5;+ return 3;+ }+ }++ return 0;+}++static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump, sljit_sw executable_offset)+{+ sljit_s32 type = (jump->flags >> 4) & 0xf;+ sljit_sw diff;+ sljit_u16 *jump_inst;+ sljit_s32 s, j1, j2;++ if (SLJIT_UNLIKELY(type == 0)) {+ modify_imm32_const((sljit_u16*)jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);+ return;+ }++ if (jump->flags & JUMP_ADDR) {+ SLJIT_ASSERT(jump->u.target & 0x1);+ diff = ((sljit_sw)jump->u.target - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1;+ }+ else {+ SLJIT_ASSERT(jump->u.label->addr & 0x1);+ diff = ((sljit_sw)(jump->u.label->addr) - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1;+ }+ jump_inst = (sljit_u16*)jump->addr;++ switch (type) {+ case 1:+ /* Encoding T1 of 'B' instruction */+ SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_COND));+ jump_inst[0] = 0xd000 | (jump->flags & 0xf00) | (diff & 0xff);+ return;+ case 2:+ /* Encoding T3 of 'B' instruction */+ SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_COND));+ jump_inst[0] = 0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1);+ jump_inst[1] = 0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | (diff & 0x7ff);+ return;+ case 3:+ SLJIT_ASSERT(jump->flags & IS_COND);+ *jump_inst++ = IT | ((jump->flags >> 4) & 0xf0) | 0x8;+ diff--;+ type = 5;+ break;+ case 4:+ /* Encoding T2 of 'B' instruction */+ SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_COND));+ jump_inst[0] = 0xe000 | (diff & 0x7ff);+ return;+ }++ SLJIT_ASSERT(diff <= 8388607 && diff >= -8388608);++ /* Really complex instruction form for branches. */+ s = (diff >> 23) & 0x1;+ j1 = (~(diff >> 22) ^ s) & 0x1;+ j2 = (~(diff >> 21) ^ s) & 0x1;+ jump_inst[0] = 0xf000 | (s << 10) | COPY_BITS(diff, 11, 0, 10);+ jump_inst[1] = (j1 << 13) | (j2 << 11) | (diff & 0x7ff);++ /* The others have a common form. */+ if (type == 5) /* Encoding T4 of 'B' instruction */+ jump_inst[1] |= 0x9000;+ else if (type == 6) /* Encoding T1 of 'BL' instruction */+ jump_inst[1] |= 0xd000;+ else+ SLJIT_UNREACHABLE();+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf;+ sljit_u16 *code;+ sljit_u16 *code_ptr;+ sljit_u16 *buf_ptr;+ sljit_u16 *buf_end;+ sljit_uw half_count;+ sljit_uw next_addr;+ sljit_sw executable_offset;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ struct sljit_put_label *put_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));+ reverse_buf(compiler);++ code = (sljit_u16*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_u16), compiler->exec_allocator_data);+ PTR_FAIL_WITH_EXEC_IF(code);+ buf = compiler->buf;++ code_ptr = code;+ half_count = 0;+ next_addr = 0;+ executable_offset = SLJIT_EXEC_OFFSET(code);++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ put_label = compiler->put_labels;++ do {+ buf_ptr = (sljit_u16*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 1);+ do {+ *code_ptr = *buf_ptr++;+ if (next_addr == half_count) {+ SLJIT_ASSERT(!label || label->size >= half_count);+ SLJIT_ASSERT(!jump || jump->addr >= half_count);+ SLJIT_ASSERT(!const_ || const_->addr >= half_count);+ SLJIT_ASSERT(!put_label || put_label->addr >= half_count);++ /* These structures are ordered by their address. */+ if (label && label->size == half_count) {+ label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;+ label->size = code_ptr - code;+ label = label->next;+ }+ if (jump && jump->addr == half_count) {+ jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);+ code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);+ jump = jump->next;+ }+ if (const_ && const_->addr == half_count) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ }+ if (put_label && put_label->addr == half_count) {+ SLJIT_ASSERT(put_label->label);+ put_label->addr = (sljit_uw)code_ptr;+ put_label = put_label->next;+ }+ next_addr = compute_next_addr(label, jump, const_, put_label);+ }+ code_ptr ++;+ half_count ++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == half_count) {+ label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;+ label->size = code_ptr - code;+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(!put_label);+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);++ jump = compiler->jumps;+ while (jump) {+ set_jump_instruction(jump, executable_offset);+ jump = jump->next;+ }++ put_label = compiler->put_labels;+ while (put_label) {+ modify_imm32_const((sljit_u16 *)put_label->addr, put_label->label->addr);+ put_label = put_label->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (code_ptr - code) * sizeof(sljit_u16);++ code = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);+ code_ptr = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ SLJIT_CACHE_FLUSH(code, code_ptr);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);++ /* Set thumb mode flag. */+ return (void*)((sljit_uw)code | 0x1);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ switch (feature_type) {+ case SLJIT_HAS_FPU:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return SLJIT_IS_FPU_AVAILABLE;+#else+ /* Available by default. */+ return 1;+#endif++ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_CMOV:+ case SLJIT_HAS_PREFETCH:+ return 1;++ default:+ return 0;+ }+}++/* --------------------------------------------------------------------- */+/* Core code generator functions. */+/* --------------------------------------------------------------------- */++#define INVALID_IMM 0x80000000+static sljit_uw get_imm(sljit_uw imm)+{+ /* Thumb immediate form. */+ sljit_s32 counter;++ if (imm <= 0xff)+ return imm;++ if ((imm & 0xffff) == (imm >> 16)) {+ /* Some special cases. */+ if (!(imm & 0xff00))+ return (1 << 12) | (imm & 0xff);+ if (!(imm & 0xff))+ return (2 << 12) | ((imm >> 8) & 0xff);+ if ((imm & 0xff00) == ((imm & 0xff) << 8))+ return (3 << 12) | (imm & 0xff);+ }++ /* Assembly optimization: count leading zeroes? */+ counter = 8;+ if (!(imm & 0xffff0000)) {+ counter += 16;+ imm <<= 16;+ }+ if (!(imm & 0xff000000)) {+ counter += 8;+ imm <<= 8;+ }+ if (!(imm & 0xf0000000)) {+ counter += 4;+ imm <<= 4;+ }+ if (!(imm & 0xc0000000)) {+ counter += 2;+ imm <<= 2;+ }+ if (!(imm & 0x80000000)) {+ counter += 1;+ imm <<= 1;+ }+ /* Since imm >= 128, this must be true. */+ SLJIT_ASSERT(counter <= 31);++ if (imm & 0x00ffffff)+ return INVALID_IMM; /* Cannot be encoded. */++ return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1);+}++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)+{+ sljit_uw tmp;++ /* MOVS cannot be used since it destroy flags. */++ if (imm >= 0x10000) {+ tmp = get_imm(imm);+ if (tmp != INVALID_IMM)+ return push_inst32(compiler, MOV_WI | RD4(dst) | tmp);+ tmp = get_imm(~imm);+ if (tmp != INVALID_IMM)+ return push_inst32(compiler, MVN_WI | RD4(dst) | tmp);+ }++ /* set low 16 bits, set hi 16 bits to 0. */+ FAIL_IF(push_inst32(compiler, MOVW | RD4(dst)+ | COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));++ /* set hi 16 bit if needed. */+ if (imm >= 0x10000)+ return push_inst32(compiler, MOVT | RD4(dst)+ | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));+ return SLJIT_SUCCESS;+}++#define ARG1_IMM 0x0010000+#define ARG2_IMM 0x0020000+/* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */+#define SET_FLAGS 0x0100000+#define UNUSED_RETURN 0x0200000++static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 dst, sljit_uw arg1, sljit_uw arg2)+{+ /* dst must be register, TMP_REG1+ arg1 must be register, imm+ arg2 must be register, imm */+ sljit_s32 reg;+ sljit_uw imm, nimm;++ if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {+ /* Both are immediates, no temporaries are used. */+ flags &= ~ARG1_IMM;+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));+ arg1 = TMP_REG1;+ }++ if (flags & (ARG1_IMM | ARG2_IMM)) {+ reg = (flags & ARG2_IMM) ? arg1 : arg2;+ imm = (flags & ARG2_IMM) ? arg2 : arg1;++ switch (flags & 0xffff) {+ case SLJIT_CLZ:+ case SLJIT_MUL:+ /* No form with immediate operand. */+ break;+ case SLJIT_MOV:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG2);+ return load_immediate(compiler, dst, imm);+ case SLJIT_NOT:+ if (!(flags & SET_FLAGS))+ return load_immediate(compiler, dst, ~imm);+ /* Since the flags should be set, we just fallback to the register mode.+ Although some clever things could be done here, "NOT IMM" does not worth the efforts. */+ break;+ case SLJIT_ADD:+ nimm = -(sljit_sw)imm;+ if (IS_2_LO_REGS(reg, dst)) {+ if (imm <= 0x7)+ return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));+ if (nimm <= 0x7)+ return push_inst16(compiler, SUBSI3 | IMM3(nimm) | RD3(dst) | RN3(reg));+ if (reg == dst) {+ if (imm <= 0xff)+ return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst));+ if (nimm <= 0xff)+ return push_inst16(compiler, SUBSI8 | IMM8(nimm) | RDN3(dst));+ }+ }+ if (!(flags & SET_FLAGS)) {+ if (imm <= 0xfff)+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm));+ if (nimm <= 0xfff)+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm));+ }+ nimm = get_imm(imm);+ if (nimm != INVALID_IMM)+ return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);+ nimm = get_imm(-(sljit_sw)imm);+ if (nimm != INVALID_IMM)+ return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);+ break;+ case SLJIT_ADDC:+ imm = get_imm(imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_SUB:+ /* SUB operation can be replaced by ADD because of the negative carry flag. */+ if (flags & ARG1_IMM) {+ if (imm == 0 && IS_2_LO_REGS(reg, dst))+ return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));+ imm = get_imm(imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ }+ if (flags & UNUSED_RETURN) {+ if (imm <= 0xff && reg_map[reg] <= 7)+ return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));+ nimm = get_imm(imm);+ if (nimm != INVALID_IMM)+ return push_inst32(compiler, CMPI_W | RN4(reg) | nimm);+ nimm = get_imm(-(sljit_sw)imm);+ if (nimm != INVALID_IMM)+ return push_inst32(compiler, CMNI_W | RN4(reg) | nimm);+ }+ nimm = -(sljit_sw)imm;+ if (IS_2_LO_REGS(reg, dst)) {+ if (imm <= 0x7)+ return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));+ if (nimm <= 0x7)+ return push_inst16(compiler, ADDSI3 | IMM3(nimm) | RD3(dst) | RN3(reg));+ if (reg == dst) {+ if (imm <= 0xff)+ return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst));+ if (nimm <= 0xff)+ return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst));+ }+ }+ if (!(flags & SET_FLAGS)) {+ if (imm <= 0xfff)+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));+ if (nimm <= 0xfff)+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm));+ }+ nimm = get_imm(imm);+ if (nimm != INVALID_IMM)+ return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);+ nimm = get_imm(-(sljit_sw)imm);+ if (nimm != INVALID_IMM)+ return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);+ break;+ case SLJIT_SUBC:+ if (flags & ARG1_IMM)+ break;+ imm = get_imm(imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_AND:+ nimm = get_imm(imm);+ if (nimm != INVALID_IMM)+ return push_inst32(compiler, ANDI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);+ imm = get_imm(imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_OR:+ nimm = get_imm(imm);+ if (nimm != INVALID_IMM)+ return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);+ imm = get_imm(imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_XOR:+ imm = get_imm(imm);+ if (imm != INVALID_IMM)+ return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);+ break;+ case SLJIT_SHL:+ case SLJIT_LSHR:+ case SLJIT_ASHR:+ if (flags & ARG1_IMM)+ break;+ imm &= 0x1f;+ if (imm == 0) {+ if (!(flags & SET_FLAGS))+ return push_inst16(compiler, MOV | SET_REGS44(dst, reg));+ if (IS_2_LO_REGS(dst, reg))+ return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));+ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));+ }+ switch (flags & 0xffff) {+ case SLJIT_SHL:+ if (IS_2_LO_REGS(dst, reg))+ return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6));+ return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));+ case SLJIT_LSHR:+ if (IS_2_LO_REGS(dst, reg))+ return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6));+ return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));+ default: /* SLJIT_ASHR */+ if (IS_2_LO_REGS(dst, reg))+ return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6));+ return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));+ }+ default:+ SLJIT_UNREACHABLE();+ break;+ }++ if (flags & ARG2_IMM) {+ imm = arg2;+ arg2 = (arg1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(load_immediate(compiler, arg2, imm));+ }+ else {+ imm = arg1;+ arg1 = (arg2 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(load_immediate(compiler, arg1, imm));+ }++ SLJIT_ASSERT(arg1 != arg2);+ }++ /* Both arguments are registers. */+ switch (flags & 0xffff) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);+ if (dst == arg2)+ return SLJIT_SUCCESS;+ return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));+ case SLJIT_MOV_U8:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);+ if (IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, UXTB | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, UXTB_W | RD4(dst) | RM4(arg2));+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);+ if (IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, SXTB | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, SXTB_W | RD4(dst) | RM4(arg2));+ case SLJIT_MOV_U16:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);+ if (IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, UXTH | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, UXTH_W | RD4(dst) | RM4(arg2));+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);+ if (IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, SXTH_W | RD4(dst) | RM4(arg2));+ case SLJIT_NOT:+ SLJIT_ASSERT(arg1 == TMP_REG2);+ if (IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, MVNS | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(arg2));+ case SLJIT_CLZ:+ SLJIT_ASSERT(arg1 == TMP_REG2);+ FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)));+ return SLJIT_SUCCESS;+ case SLJIT_ADD:+ if (IS_3_LO_REGS(dst, arg1, arg2))+ return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2));+ if (dst == arg1 && !(flags & SET_FLAGS))+ return push_inst16(compiler, ADD | SET_REGS44(dst, arg2));+ return push_inst32(compiler, ADD_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_ADDC:+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_SUB:+ if (flags & UNUSED_RETURN) {+ if (IS_2_LO_REGS(arg1, arg2))+ return push_inst16(compiler, CMP | RD3(arg1) | RN3(arg2));+ return push_inst16(compiler, CMP_X | SET_REGS44(arg1, arg2));+ }+ if (IS_3_LO_REGS(dst, arg1, arg2))+ return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2));+ return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_SUBC:+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, SBCS | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, SBC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_MUL:+ if (!(flags & SET_FLAGS))+ return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2));+ SLJIT_ASSERT(dst != TMP_REG2);+ FAIL_IF(push_inst32(compiler, SMULL | RT4(dst) | RD4(TMP_REG2) | RN4(arg1) | RM4(arg2)));+ /* cmp TMP_REG2, dst asr #31. */+ return push_inst32(compiler, CMP_W | RN4(TMP_REG2) | 0x70e0 | RM4(dst));+ case SLJIT_AND:+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2));+ if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2))+ return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2));+ return push_inst32(compiler, AND_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_OR:+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, ORRS | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, ORR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_XOR:+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_SHL:+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_LSHR:+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ case SLJIT_ASHR:+ if (dst == arg1 && IS_2_LO_REGS(dst, arg2))+ return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2));+ return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++#define STORE 0x01+#define SIGNED 0x02++#define WORD_SIZE 0x00+#define BYTE_SIZE 0x04+#define HALF_SIZE 0x08+#define PRELOAD 0x0c++#define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE)))+#define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift)))++/*+ 1st letter:+ w = word+ b = byte+ h = half++ 2nd letter:+ s = signed+ u = unsigned++ 3rd letter:+ l = load+ s = store+*/++static const sljit_ins sljit_mem16[12] = {+/* w u l */ 0x5800 /* ldr */,+/* w u s */ 0x5000 /* str */,+/* w s l */ 0x5800 /* ldr */,+/* w s s */ 0x5000 /* str */,++/* b u l */ 0x5c00 /* ldrb */,+/* b u s */ 0x5400 /* strb */,+/* b s l */ 0x5600 /* ldrsb */,+/* b s s */ 0x5400 /* strb */,++/* h u l */ 0x5a00 /* ldrh */,+/* h u s */ 0x5200 /* strh */,+/* h s l */ 0x5e00 /* ldrsh */,+/* h s s */ 0x5200 /* strh */,+};++static const sljit_ins sljit_mem16_imm5[12] = {+/* w u l */ 0x6800 /* ldr imm5 */,+/* w u s */ 0x6000 /* str imm5 */,+/* w s l */ 0x6800 /* ldr imm5 */,+/* w s s */ 0x6000 /* str imm5 */,++/* b u l */ 0x7800 /* ldrb imm5 */,+/* b u s */ 0x7000 /* strb imm5 */,+/* b s l */ 0x0000 /* not allowed */,+/* b s s */ 0x7000 /* strb imm5 */,++/* h u l */ 0x8800 /* ldrh imm5 */,+/* h u s */ 0x8000 /* strh imm5 */,+/* h s l */ 0x0000 /* not allowed */,+/* h s s */ 0x8000 /* strh imm5 */,+};++#define MEM_IMM8 0xc00+#define MEM_IMM12 0x800000+static const sljit_ins sljit_mem32[13] = {+/* w u l */ 0xf8500000 /* ldr.w */,+/* w u s */ 0xf8400000 /* str.w */,+/* w s l */ 0xf8500000 /* ldr.w */,+/* w s s */ 0xf8400000 /* str.w */,++/* b u l */ 0xf8100000 /* ldrb.w */,+/* b u s */ 0xf8000000 /* strb.w */,+/* b s l */ 0xf9100000 /* ldrsb.w */,+/* b s s */ 0xf8000000 /* strb.w */,++/* h u l */ 0xf8300000 /* ldrh.w */,+/* h u s */ 0xf8200000 /* strsh.w */,+/* h s l */ 0xf9300000 /* ldrsh.w */,+/* h s s */ 0xf8200000 /* strsh.w */,++/* p u l */ 0xf8100000 /* pld */,+};++/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */+static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value)+{+ if (value >= 0) {+ if (value <= 0xfff)+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(value));+ value = get_imm(value);+ if (value != INVALID_IMM)+ return push_inst32(compiler, ADD_WI | RD4(dst) | RN4(reg) | value);+ }+ else {+ value = -value;+ if (value <= 0xfff)+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(value));+ value = get_imm(value);+ if (value != INVALID_IMM)+ return push_inst32(compiler, SUB_WI | RD4(dst) | RN4(reg) | value);+ }+ return SLJIT_ERR_UNSUPPORTED;+}++static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)+{+ sljit_s32 other_r;+ sljit_uw tmp;++ SLJIT_ASSERT(arg & SLJIT_MEM);+ SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);+ arg &= ~SLJIT_MEM;++ if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {+ tmp = get_imm(argw & ~0xfff);+ if (tmp != INVALID_IMM) {+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(tmp_reg) | tmp));+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg) | (argw & 0xfff));+ }++ FAIL_IF(load_immediate(compiler, tmp_reg, argw));+ if (IS_2_LO_REGS(reg, tmp_reg) && sljit_mem16_imm5[flags])+ return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(tmp_reg));+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg));+ }++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;+ other_r = OFFS_REG(arg);+ arg &= 0xf;++ if (!argw && IS_3_LO_REGS(reg, arg, other_r))+ return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r));+ return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4));+ }++ if (argw > 0xfff) {+ tmp = get_imm(argw & ~0xfff);+ if (tmp != INVALID_IMM) {+ push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp);+ arg = tmp_reg;+ argw = argw & 0xfff;+ }+ }+ else if (argw < -0xff) {+ tmp = get_imm(-argw & ~0xff);+ if (tmp != INVALID_IMM) {+ push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp);+ arg = tmp_reg;+ argw = -(-argw & 0xff);+ }+ }++ if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {+ tmp = 3;+ if (IS_WORD_SIZE(flags)) {+ if (OFFSET_CHECK(0x1f, 2))+ tmp = 2;+ }+ else if (flags & BYTE_SIZE)+ {+ if (OFFSET_CHECK(0x1f, 0))+ tmp = 0;+ }+ else {+ SLJIT_ASSERT(flags & HALF_SIZE);+ if (OFFSET_CHECK(0x1f, 1))+ tmp = 1;+ }++ if (tmp < 3)+ return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - tmp)));+ }+ else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && OFFSET_CHECK(0xff, 2) && reg_map[reg] <= 7) {+ /* SP based immediate. */+ return push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2));+ }++ if (argw >= 0 && argw <= 0xfff)+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw);+ else if (argw < 0 && argw >= -0xff)+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw);++ SLJIT_ASSERT(arg != tmp_reg);++ FAIL_IF(load_immediate(compiler, tmp_reg, argw));+ if (IS_3_LO_REGS(reg, arg, tmp_reg))+ return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg));+ return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg));+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 args, size, i, tmp;+ sljit_ins push = 0;+#ifdef _WIN32+ sljit_uw imm;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = SLJIT_S0; i >= tmp; i--)+ push |= 1 << reg_map[i];++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)+ push |= 1 << reg_map[i];++ FAIL_IF((push & 0xff00)+ ? push_inst32(compiler, PUSH_W | (1 << 14) | push)+ : push_inst16(compiler, PUSH | (1 << 8) | push));++ /* Stack must be aligned to 8 bytes: (LR, R4) */+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);+ local_size = ((size + local_size + 7) & ~7) - size;+ compiler->local_size = local_size;++#ifdef _WIN32+ if (local_size >= 256) {+ if (local_size > 4096)+ imm = get_imm(4096);+ else+ imm = get_imm(local_size & ~0xff);++ SLJIT_ASSERT(imm != INVALID_IMM);+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(SLJIT_SP) | imm));+ }+#else+ if (local_size > 0) {+ if (local_size <= (127 << 2))+ FAIL_IF(push_inst16(compiler, SUB_SP | (local_size >> 2)));+ else+ FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, local_size));+ }+#endif++ args = get_arg_count(arg_types);++ if (args >= 1)+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0, SLJIT_R0)));+ if (args >= 2)+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S1, SLJIT_R1)));+ if (args >= 3)+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S2, SLJIT_R2)));++#ifdef _WIN32+ if (local_size >= 256) {+ if (local_size > 4096) {+ imm = get_imm(4096);+ SLJIT_ASSERT(imm != INVALID_IMM);++ if (local_size < 4 * 4096) {+ if (local_size > 2 * 4096) {+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));+ local_size -= 4096;+ }++ if (local_size > 2 * 4096) {+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));+ local_size -= 4096;+ }++ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));+ local_size -= 4096;++ SLJIT_ASSERT(local_size > 0);+ }+ else {+ FAIL_IF(load_immediate(compiler, SLJIT_R3, (local_size >> 12) - 1));+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));+ SLJIT_ASSERT(reg_map[SLJIT_R3] < 7);+ FAIL_IF(push_inst16(compiler, SUBSI8 | RDN3(SLJIT_R3) | 1));+ FAIL_IF(push_inst16(compiler, BCC | (0x1 << 8) /* not-equal */ | (-7 & 0xff)));++ local_size &= 0xfff;++ if (local_size != 0)+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));+ }++ if (local_size >= 256) {+ imm = get_imm(local_size & ~0xff);+ SLJIT_ASSERT(imm != INVALID_IMM);++ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));+ }+ }++ local_size &= 0xff;+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | (local_size > 0 ? 0x100 : 0) | RT4(TMP_REG2) | RN4(TMP_REG1) | local_size));++ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SP, TMP_REG1)));+ }+ else if (local_size > 0)+ FAIL_IF(push_inst32(compiler, LDRI | 0x500 | RT4(TMP_REG1) | RN4(SLJIT_SP) | local_size));+#endif++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);+ compiler->local_size = ((size + local_size + 7) & ~7) - size;+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 i, tmp;+ sljit_ins pop = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));++ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));++ if (compiler->local_size > 0) {+ if (compiler->local_size <= (127 << 2))+ FAIL_IF(push_inst16(compiler, ADD_SP | (compiler->local_size >> 2)));+ else+ FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_SP, SLJIT_SP, compiler->local_size));+ }++ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = SLJIT_S0; i >= tmp; i--)+ pop |= 1 << reg_map[i];++ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--)+ pop |= 1 << reg_map[i];++ return (pop & 0xff00)+ ? push_inst32(compiler, POP_W | (1 << 15) | pop)+ : push_inst16(compiler, POP | (1 << 8) | pop);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)++#ifdef __cplusplus+extern "C" {+#endif++#ifdef _WIN32+extern unsigned long long __rt_udiv(unsigned int denominator, unsigned int numerator);+extern long long __rt_sdiv(int denominator, int numerator);+#elif defined(__GNUC__)+extern unsigned int __aeabi_uidivmod(unsigned int numerator, int unsigned denominator);+extern int __aeabi_idivmod(int numerator, int denominator);+#else+#error "Software divmod functions are needed"+#endif++#ifdef __cplusplus+}+#endif++#endif /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)+ sljit_sw saved_reg_list[3];+ sljit_sw saved_reg_count;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ return push_inst16(compiler, BKPT);+ case SLJIT_NOP:+ return push_inst16(compiler, NOP);+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+ return push_inst32(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)+ | (reg_map[SLJIT_R1] << 8)+ | (reg_map[SLJIT_R0] << 12)+ | (reg_map[SLJIT_R0] << 16)+ | reg_map[SLJIT_R1]);+#if (defined __ARM_FEATURE_IDIV) || (defined __ARM_ARCH_EXT_IDIV__)+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIVMOD_SW:+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0)));+ FAIL_IF(push_inst32(compiler, (op == SLJIT_DIVMOD_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1)));+ FAIL_IF(push_inst32(compiler, MUL | RD4(SLJIT_R1) | RN4(SLJIT_R0) | RM4(SLJIT_R1)));+ return push_inst32(compiler, SUB_W | RD4(SLJIT_R1) | RN4(TMP_REG1) | RM4(SLJIT_R1));+ case SLJIT_DIV_UW:+ case SLJIT_DIV_SW:+ return push_inst32(compiler, (op == SLJIT_DIV_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1));+#else /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIVMOD_SW:+ case SLJIT_DIV_UW:+ case SLJIT_DIV_SW:+ SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);+ SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3);++ saved_reg_count = 0;+ if (compiler->scratches >= 4)+ saved_reg_list[saved_reg_count++] = 3;+ if (compiler->scratches >= 3)+ saved_reg_list[saved_reg_count++] = 2;+ if (op >= SLJIT_DIV_UW)+ saved_reg_list[saved_reg_count++] = 1;++ if (saved_reg_count > 0) {+ FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8)+ | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));+ if (saved_reg_count >= 2) {+ SLJIT_ASSERT(saved_reg_list[1] < 8);+ FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */));+ }+ if (saved_reg_count >= 3) {+ SLJIT_ASSERT(saved_reg_list[2] < 8);+ FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */));+ }+ }++#ifdef _WIN32+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0)));+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R0, SLJIT_R1)));+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R1, TMP_REG1)));+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__rt_udiv) : SLJIT_FUNC_OFFSET(__rt_sdiv))));+#elif defined(__GNUC__)+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));+#else+#error "Software divmod functions are needed"+#endif++ if (saved_reg_count > 0) {+ if (saved_reg_count >= 3) {+ SLJIT_ASSERT(saved_reg_list[2] < 8);+ FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */));+ }+ if (saved_reg_count >= 2) {+ SLJIT_ASSERT(saved_reg_list[1] < 8);+ FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */));+ }+ return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8)+ | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);+ }+ return SLJIT_SUCCESS;+#endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r, flags;+ sljit_s32 op_flags = GET_ALL_FLAGS(op);++ CHECK_ERROR();+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;++ op = GET_OPCODE(op);+ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {+ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV_P:+ flags = WORD_SIZE;+ break;+ case SLJIT_MOV_U8:+ flags = BYTE_SIZE;+ if (src & SLJIT_IMM)+ srcw = (sljit_u8)srcw;+ break;+ case SLJIT_MOV_S8:+ flags = BYTE_SIZE | SIGNED;+ if (src & SLJIT_IMM)+ srcw = (sljit_s8)srcw;+ break;+ case SLJIT_MOV_U16:+ flags = HALF_SIZE;+ if (src & SLJIT_IMM)+ srcw = (sljit_u16)srcw;+ break;+ case SLJIT_MOV_S16:+ flags = HALF_SIZE | SIGNED;+ if (src & SLJIT_IMM)+ srcw = (sljit_s16)srcw;+ break;+ default:+ SLJIT_UNREACHABLE();+ flags = 0;+ break;+ }++ if (src & SLJIT_IMM)+ FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, srcw));+ else if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, TMP_REG1));+ } else {+ if (dst_r != TMP_REG1)+ return emit_op_imm(compiler, op, dst_r, TMP_REG2, src);+ dst_r = src;+ }++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;++ return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);+ }++ if (op == SLJIT_NEG) {+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ return sljit_emit_op2(compiler, SLJIT_SUB | op_flags, dst, dstw, SLJIT_IMM, 0, src, srcw);+ }++ flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, src);++ if (SLJIT_UNLIKELY(dst & SLJIT_MEM))+ return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 dst_reg, flags, src2_reg;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))+ return SLJIT_SUCCESS;++ dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG1;+ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;++ if (src1 & SLJIT_IMM)+ flags |= ARG1_IMM;+ else if (src1 & SLJIT_MEM) {+ emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1);+ src1w = TMP_REG1;+ }+ else+ src1w = src1;++ if (src2 & SLJIT_IMM)+ flags |= ARG2_IMM;+ else if (src2 & SLJIT_MEM) {+ src2_reg = (!(flags & ARG1_IMM) && (src1w == TMP_REG1)) ? TMP_REG2 : TMP_REG1;+ emit_op_mem(compiler, WORD_SIZE, src2_reg, src2, src2w, src2_reg);+ src2w = src2_reg;+ }+ else+ src2w = src2;++ if (dst == SLJIT_UNUSED)+ flags |= UNUSED_RETURN;++ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_reg, src1w, src2w);++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG2);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ if (FAST_IS_REG(src))+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));++ return push_inst16(compiler, BX | RN3(TMP_REG2));+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(reg));+ return reg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));+ return (freg_map[reg] << 1);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ if (size == 2)+ return push_inst16(compiler, *(sljit_u16*)instruction);+ return push_inst32(compiler, *(sljit_ins*)instruction);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++#define FPU_LOAD (1 << 20)++static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ sljit_uw imm;+ sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD));++ SLJIT_ASSERT(arg & SLJIT_MEM);++ /* Fast loads and stores. */+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6)));+ arg = SLJIT_MEM | TMP_REG1;+ argw = 0;+ }++ if ((arg & REG_MASK) && (argw & 0x3) == 0) {+ if (!(argw & ~0x3fc))+ return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | DD4(reg) | (argw >> 2));+ if (!(-argw & ~0x3fc))+ return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | (-argw >> 2));+ }++ if (arg & REG_MASK) {+ if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {+ FAIL_IF(compiler->error);+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg));+ }+ imm = get_imm(argw & ~0x3fc);+ if (imm != INVALID_IMM) {+ FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2));+ }+ imm = get_imm(-argw & ~0x3fc);+ if (imm != INVALID_IMM) {+ argw = -argw;+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));+ return push_inst32(compiler, inst | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2));+ }+ }++ FAIL_IF(load_immediate(compiler, TMP_REG1, argw));+ if (arg & REG_MASK)+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, (arg & REG_MASK))));+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg));+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ op ^= SLJIT_F32_OP;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw));+ src = TMP_FREG1;+ }++ FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_F32_OP) | DD4(TMP_FREG1) | DM4(src)));++ if (FAST_IS_REG(dst))+ return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | DN4(TMP_FREG1));++ /* Store the integer value from a VFP register. */+ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ op ^= SLJIT_F32_OP;++ if (FAST_IS_REG(src))+ FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | DN4(TMP_FREG1)));+ else if (src & SLJIT_MEM) {+ /* Load the integer value into a VFP register. */+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));+ }+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | DN4(TMP_FREG1)));+ }++ FAIL_IF(push_inst32(compiler, VCVT_F32_S32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(TMP_FREG1)));++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ op ^= SLJIT_F32_OP;++ if (src1 & SLJIT_MEM) {+ emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);+ src2 = TMP_FREG2;+ }++ FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_F32_OP) | DD4(src1) | DM4(src2)));+ return push_inst32(compiler, VMRS);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r;++ CHECK_ERROR();++ SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)+ op ^= SLJIT_F32_OP;++ if (src & SLJIT_MEM) {+ emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw);+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (dst_r != TMP_FREG1)+ FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));+ op ^= SLJIT_F32_OP;+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_fop_mem(compiler, (op & SLJIT_F32_OP), dst_r, dst, dstw);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ op ^= SLJIT_F32_OP;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;+ if (src1 & SLJIT_MEM) {+ emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);+ src1 = TMP_FREG1;+ }+ if (src2 & SLJIT_MEM) {+ emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);+ src2 = TMP_FREG2;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));+ break;+ case SLJIT_SUB_F64:+ FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));+ break;+ case SLJIT_MUL_F64:+ FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));+ break;+ case SLJIT_DIV_F64:+ FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));+ break;+ }++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;+ return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw);+}++#undef FPU_LOAD++/* --------------------------------------------------------------------- */+/* Other instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ if (FAST_IS_REG(dst))+ return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2));++ /* Memory. */+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++static sljit_uw get_cc(sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_MUL_NOT_OVERFLOW:+ case SLJIT_EQUAL_F64:+ return 0x0;++ case SLJIT_NOT_EQUAL:+ case SLJIT_MUL_OVERFLOW:+ case SLJIT_NOT_EQUAL_F64:+ return 0x1;++ case SLJIT_LESS:+ case SLJIT_LESS_F64:+ return 0x3;++ case SLJIT_GREATER_EQUAL:+ case SLJIT_GREATER_EQUAL_F64:+ return 0x2;++ case SLJIT_GREATER:+ case SLJIT_GREATER_F64:+ return 0x8;++ case SLJIT_LESS_EQUAL:+ case SLJIT_LESS_EQUAL_F64:+ return 0x9;++ case SLJIT_SIG_LESS:+ return 0xb;++ case SLJIT_SIG_GREATER_EQUAL:+ return 0xa;++ case SLJIT_SIG_GREATER:+ return 0xc;++ case SLJIT_SIG_LESS_EQUAL:+ return 0xd;++ case SLJIT_OVERFLOW:+ case SLJIT_UNORDERED_F64:+ return 0x6;++ case SLJIT_NOT_OVERFLOW:+ case SLJIT_ORDERED_F64:+ return 0x7;++ default: /* SLJIT_JUMP */+ SLJIT_UNREACHABLE();+ return 0xe;+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;+ sljit_ins cc;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));+ if (type < SLJIT_JUMP) {+ jump->flags |= IS_COND;+ cc = get_cc(type);+ jump->flags |= cc << 8;+ PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ }++ jump->addr = compiler->size;+ if (type <= SLJIT_JUMP)+ PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG1)));+ else {+ jump->flags |= IS_BL;+ PTR_FAIL_IF(push_inst16(compiler, BLX | RN3(TMP_REG1)));+ }++ return jump;+}++#ifdef __SOFTFP__++static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)+{+ sljit_s32 stack_offset = 0;+ sljit_s32 arg_count = 0;+ sljit_s32 word_arg_offset = 0;+ sljit_s32 float_arg_count = 0;+ sljit_s32 types = 0;+ sljit_s32 src_offset = 4 * sizeof(sljit_sw);+ sljit_u8 offsets[4];++ if (src && FAST_IS_REG(*src))+ src_offset = reg_map[*src] * sizeof(sljit_sw);++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);++ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ offsets[arg_count] = (sljit_u8)stack_offset;+ stack_offset += sizeof(sljit_f32);+ arg_count++;+ float_arg_count++;+ break;+ case SLJIT_ARG_TYPE_F64:+ if (stack_offset & 0x7)+ stack_offset += sizeof(sljit_sw);+ offsets[arg_count] = (sljit_u8)stack_offset;+ stack_offset += sizeof(sljit_f64);+ arg_count++;+ float_arg_count++;+ break;+ default:+ offsets[arg_count] = (sljit_u8)stack_offset;+ stack_offset += sizeof(sljit_sw);+ arg_count++;+ word_arg_offset += sizeof(sljit_sw);+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ if (stack_offset > 16)+ FAIL_IF(push_inst16(compiler, SUB_SP | (((stack_offset - 16) + 0x7) & ~0x7) >> 2));++ SLJIT_ASSERT(reg_map[TMP_REG1] == 12);++ /* Process arguments in reversed direction. */+ while (types) {+ switch (types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ arg_count--;+ float_arg_count--;+ stack_offset = offsets[arg_count];++ if (stack_offset < 16) {+ if (src_offset == stack_offset) {+ FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));+ *src = TMP_REG1;+ }+ FAIL_IF(push_inst32(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (stack_offset << 10)));+ } else+ FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800000 | RN4(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2)));+ break;+ case SLJIT_ARG_TYPE_F64:+ arg_count--;+ float_arg_count--;+ stack_offset = offsets[arg_count];++ SLJIT_ASSERT((stack_offset & 0x7) == 0);++ if (stack_offset < 16) {+ if (src_offset == stack_offset || src_offset == stack_offset + sizeof(sljit_sw)) {+ FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));+ *src = TMP_REG1;+ }+ FAIL_IF(push_inst32(compiler, VMOV2 | 0x100000 | (stack_offset << 10) | ((stack_offset + sizeof(sljit_sw)) << 14) | float_arg_count));+ } else+ FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800100 | RN4(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2)));+ break;+ default:+ arg_count--;+ word_arg_offset -= sizeof(sljit_sw);+ stack_offset = offsets[arg_count];++ SLJIT_ASSERT(stack_offset >= word_arg_offset);++ if (stack_offset != word_arg_offset) {+ if (stack_offset < 16) {+ if (src_offset == stack_offset) {+ FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));+ *src = TMP_REG1;+ }+ else if (src_offset == word_arg_offset) {+ *src = 1 + (stack_offset >> 2);+ src_offset = stack_offset;+ }+ FAIL_IF(push_inst16(compiler, MOV | (stack_offset >> 2) | (word_arg_offset << 1)));+ } else+ FAIL_IF(push_inst16(compiler, STR_SP | (word_arg_offset << 6) | ((stack_offset - 16) >> 2)));+ }+ break;+ }++ types >>= SLJIT_DEF_SHIFT;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)+{+ sljit_s32 stack_size = 0;++ if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32)+ FAIL_IF(push_inst32(compiler, VMOV | (0 << 16) | (0 << 12)));+ if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64)+ FAIL_IF(push_inst32(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ stack_size += sizeof(sljit_f32);+ break;+ case SLJIT_ARG_TYPE_F64:+ if (stack_size & 0x7)+ stack_size += sizeof(sljit_sw);+ stack_size += sizeof(sljit_f64);+ break;+ default:+ stack_size += sizeof(sljit_sw);+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ if (stack_size <= 16)+ return SLJIT_SUCCESS;++ return push_inst16(compiler, ADD_SP | ((((stack_size - 16) + 0x7) & ~0x7) >> 2));+}++#else++static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)+{+ sljit_u32 remap = 0;+ sljit_u32 offset = 0;+ sljit_u32 new_offset, mask;++ /* Remove return value. */+ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) {+ new_offset = 0;+ mask = 1;++ while (remap & mask) {+ new_offset++;+ mask <<= 1;+ }+ remap |= mask;++ if (offset != new_offset)+ FAIL_IF(push_inst32(compiler, VMOV_F32 | DD4((new_offset >> 1) + 1)+ | ((new_offset & 0x1) ? 0x400000 : 0) | DM4((offset >> 1) + 1)));++ offset += 2;+ }+ else if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) {+ new_offset = 0;+ mask = 3;++ while (remap & mask) {+ new_offset += 2;+ mask <<= 2;+ }+ remap |= mask;++ if (offset != new_offset)+ FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_F32_OP | DD4((new_offset >> 1) + 1) | DM4((offset >> 1) + 1)));++ offset += 2;+ }+ arg_types >>= SLJIT_DEF_SHIFT;+ }++ return SLJIT_SUCCESS;+}++#endif++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+#ifdef __SOFTFP__+ struct sljit_jump *jump;+#endif++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++#ifdef __SOFTFP__+ PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ jump = sljit_emit_jump(compiler, type);+ PTR_FAIL_IF(jump == NULL);++ PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));+ return jump;+#else+ PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_jump(compiler, type);+#endif+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ struct sljit_jump *jump;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);++ if (!(src & SLJIT_IMM)) {+ if (FAST_IS_REG(src)) {+ SLJIT_ASSERT(reg_map[src] != 14);+ return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src));+ }++ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw, TMP_REG1));+ if (type >= SLJIT_FAST_CALL)+ return push_inst16(compiler, BLX | RN3(TMP_REG1));+ }++ /* These jumps are converted to jump/call instructions when possible. */+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));+ jump->u.target = srcw;++ FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));+ jump->addr = compiler->size;+ return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++#ifdef __SOFTFP__+ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));++ return softfloat_post_call_with_args(compiler, arg_types);+#else /* !__SOFTFP__ */+ FAIL_IF(hardfloat_call_with_args(compiler, arg_types));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_ijump(compiler, type, src, srcw);+#endif /* __SOFTFP__ */+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 type)+{+ sljit_s32 dst_r, flags = GET_ALL_FLAGS(op);+ sljit_ins cc;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ op = GET_OPCODE(op);+ cc = get_cc(type & 0xff);+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (op < SLJIT_ADD) {+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));+ if (reg_map[dst_r] > 7) {+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 1));+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 0));+ } else {+ /* The movsi (immediate) instruction does not set flags in IT block. */+ FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1));+ FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0));+ }+ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2);+ }++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));++ if (op == SLJIT_AND) {+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));+ FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 1));+ FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 0));+ }+ else {+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ FAIL_IF(push_inst32(compiler, ((op == SLJIT_OR) ? ORRI : EORI) | RN4(dst_r) | RD4(dst_r) | 1));+ }++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2));++ if (!(flags & SLJIT_SET_Z))+ return SLJIT_SUCCESS;++ /* The condition must always be set, even if the ORR/EORI is not executed above. */+ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_uw cc, tmp;++ CHECK_ERROR();+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));++ dst_reg &= ~SLJIT_I32_OP;++ cc = get_cc(type & 0xff);++ if (!(src & SLJIT_IMM)) {+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src));+ }++ tmp = (sljit_uw) srcw;++ if (tmp < 0x10000) {+ /* set low 16 bits, set hi 16 bits to 0. */+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ return push_inst32(compiler, MOVW | RD4(dst_reg)+ | COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff));+ }++ tmp = get_imm(srcw);+ if (tmp != INVALID_IMM) {+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp);+ }++ tmp = get_imm(~srcw);+ if (tmp != INVALID_IMM) {+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);+ }++ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4));++ tmp = (sljit_uw) srcw;+ FAIL_IF(push_inst32(compiler, MOVW | RD4(dst_reg)+ | COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff)));+ return push_inst32(compiler, MOVT | RD4(dst_reg)+ | COPY_BITS(tmp, 12 + 16, 16, 4) | COPY_BITS(tmp, 11 + 16, 26, 1) | COPY_BITS(tmp, 8 + 16, 12, 3) | ((tmp & 0xff0000) >> 16));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 flags;+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255))+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ switch (type & 0xff) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV_P:+ flags = WORD_SIZE;+ break;+ case SLJIT_MOV_U8:+ flags = BYTE_SIZE;+ break;+ case SLJIT_MOV_S8:+ flags = BYTE_SIZE | SIGNED;+ break;+ case SLJIT_MOV_U16:+ flags = HALF_SIZE;+ break;+ case SLJIT_MOV_S16:+ flags = HALF_SIZE | SIGNED;+ break;+ default:+ SLJIT_UNREACHABLE();+ flags = WORD_SIZE;+ break;+ }++ if (type & SLJIT_MEM_STORE)+ flags |= STORE;++ inst = sljit_mem32[flags] | 0x900;++ if (type & SLJIT_MEM_PRE)+ inst |= 0x400;++ if (memw >= 0)+ inst |= 0x200;+ else+ memw = -memw;++ return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | memw);+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));+ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_put_label *put_label;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));+ PTR_FAIL_IF(!put_label);+ set_put_label(put_label, compiler, 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, 0));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));+ return put_label;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ sljit_u16 *inst = (sljit_u16*)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);+ modify_imm32_const(inst, new_target);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 4);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, new_constant, executable_offset);+}
+ src/c/pcre2/src/sljit/sljitNativeMIPS_32.c view
@@ -0,0 +1,671 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/* mips 32-bit arch dependent functions. */++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)+{+ if (!(imm & ~0xffff))+ return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);++ if (imm < 0 && imm >= SIMM_MIN)+ return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);++ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));+ return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;+}++#define EMIT_LOGICAL(op_imm, op_norm) \+ if (flags & SRC2_IMM) { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \+ } \+ else { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \+ }++#define EMIT_SHIFT(op_imm, op_v) \+ if (flags & SRC2_IMM) { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \+ } \+ else { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \+ }++static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,+ sljit_s32 dst, sljit_s32 src1, sljit_sw src2)+{+ sljit_s32 is_overflow, is_carry, is_handled;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if (dst != src2)+ return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S8) {+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));+#else /* SLJIT_MIPS_REV < 1 */+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));+ return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));+#endif /* SLJIT_MIPS_REV >= 1 */+ }+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));+ }+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S16) {+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));+#else /* SLJIT_MIPS_REV < 1 */+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));+ return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));+#endif /* SLJIT_MIPS_REV >= 1 */+ }+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));+ }+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_NOT:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ if (!(flags & UNUSED_DEST))+ FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));+ return SLJIT_SUCCESS;++ case SLJIT_CLZ:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));+ if (!(flags & UNUSED_DEST))+ FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));+#else /* SLJIT_MIPS_REV < 1 */+ if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {+ FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));+ return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);+ }+ /* Nearly all instructions are unmovable in the following sequence. */+ FAIL_IF(push_inst(compiler, ADDU | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));+ /* Check zero. */+ FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst) | IMM(-1), DR(dst)));+ /* Loop for searching the highest bit. */+ FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));+ FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));+#endif /* SLJIT_MIPS_REV >= 1 */+ return SLJIT_SUCCESS;++ case SLJIT_ADD:+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));+ else+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));+ }+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));++ if (is_overflow || is_carry) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ else {+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ }+ }+ /* dst may be the same as src1 or src2. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));+ }+ else {+ if (is_overflow)+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));++ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));+ /* dst may be the same as src1 or src2. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));+ }++ /* a + b >= a | b (otherwise, the carry should be set to 1). */+ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ if (!is_overflow)+ return SLJIT_SUCCESS;+ FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));+ return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);++ case SLJIT_ADDC:+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);++ if (flags & SRC2_IMM) {+ if (is_carry) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));+ else {+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));+ }+ }+ FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));+ } else {+ if (is_carry)+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ /* dst may be the same as src1 or src2. */+ FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));+ }+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));++ FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));+ if (!is_carry)+ return SLJIT_SUCCESS;++ /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ /* Set carry flag. */+ return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);++ case SLJIT_SUB:+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ is_handled = 0;++ if (flags & SRC2_IMM) {+ if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ is_handled = 1;+ }+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {+ FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ is_handled = 1;+ }+ }++ if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {+ is_handled = 1;++ if (flags & SRC2_IMM) {+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));+ }+ else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)+ {+ FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));+ }+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {+ FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));+ }+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)+ {+ FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));+ }+ }++ if (is_handled) {+ if (flags & SRC2_IMM) {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));+ if (!(flags & UNUSED_DEST))+ return push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst));+ }+ else {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ if (!(flags & UNUSED_DEST))+ return push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst));+ }+ return SLJIT_SUCCESS;+ }++ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));+ else+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));+ }+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));++ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ /* dst may be the same as src1 or src2. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));+ }+ else {+ if (is_overflow)+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));++ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));+ /* dst may be the same as src1 or src2. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));+ }++ if (!is_overflow)+ return SLJIT_SUCCESS;+ FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));+ return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);++ case SLJIT_SUBC:+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);++ if (flags & SRC2_IMM) {+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));+ /* dst may be the same as src1 or src2. */+ FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));+ }+ else {+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ /* dst may be the same as src1 or src2. */+ FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));+ }++ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));++ FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));+ return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;++ case SLJIT_MUL:+ SLJIT_ASSERT(!(flags & SRC2_IMM));++ if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));+#else /* SLJIT_MIPS_REV < 1 */+ FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));+ return push_inst(compiler, MFLO | D(dst), DR(dst));+#endif /* SLJIT_MIPS_REV >= 1 */+ }++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ FAIL_IF(push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)));+ FAIL_IF(push_inst(compiler, MUH | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+#else /* SLJIT_MIPS_REV < 6 */+ FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));+ FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));+#endif /* SLJIT_MIPS_REV >= 6 */+ FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));+ return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);++ case SLJIT_AND:+ EMIT_LOGICAL(ANDI, AND);+ return SLJIT_SUCCESS;++ case SLJIT_OR:+ EMIT_LOGICAL(ORI, OR);+ return SLJIT_SUCCESS;++ case SLJIT_XOR:+ EMIT_LOGICAL(XORI, XOR);+ return SLJIT_SUCCESS;++ case SLJIT_SHL:+ EMIT_SHIFT(SLL, SLLV);+ return SLJIT_SUCCESS;++ case SLJIT_LSHR:+ EMIT_SHIFT(SRL, SRLV);+ return SLJIT_SUCCESS;++ case SLJIT_ASHR:+ EMIT_SHIFT(SRA, SRAV);+ return SLJIT_SUCCESS;+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)+{+ FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));+ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ sljit_ins *inst = (sljit_ins *)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);+ inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);+ inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, new_constant, executable_offset);+}++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)+{+ sljit_s32 stack_offset = 0;+ sljit_s32 arg_count = 0;+ sljit_s32 float_arg_count = 0;+ sljit_s32 word_arg_count = 0;+ sljit_s32 types = 0;+ sljit_s32 arg_count_save, types_save;+ sljit_ins prev_ins = NOP;+ sljit_ins ins = NOP;+ sljit_u8 offsets[4];++ SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);++ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ offsets[arg_count] = (sljit_u8)stack_offset;++ if (word_arg_count == 0 && arg_count <= 1)+ offsets[arg_count] = 254 + arg_count;++ stack_offset += sizeof(sljit_f32);+ arg_count++;+ float_arg_count++;+ break;+ case SLJIT_ARG_TYPE_F64:+ if (stack_offset & 0x7)+ stack_offset += sizeof(sljit_sw);+ offsets[arg_count] = (sljit_u8)stack_offset;++ if (word_arg_count == 0 && arg_count <= 1)+ offsets[arg_count] = 254 + arg_count;++ stack_offset += sizeof(sljit_f64);+ arg_count++;+ float_arg_count++;+ break;+ default:+ offsets[arg_count] = (sljit_u8)stack_offset;+ stack_offset += sizeof(sljit_sw);+ arg_count++;+ word_arg_count++;+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */+ if (stack_offset > 16)+ FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));++ types_save = types;+ arg_count_save = arg_count;++ while (types) {+ switch (types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ arg_count--;+ if (offsets[arg_count] < 254)+ ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]);+ float_arg_count--;+ break;+ case SLJIT_ARG_TYPE_F64:+ arg_count--;+ if (offsets[arg_count] < 254)+ ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]);+ float_arg_count--;+ break;+ default:+ if (offsets[arg_count - 1] >= 16)+ ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(offsets[arg_count - 1]);+ else if (arg_count != word_arg_count)+ ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (offsets[arg_count - 1] >> 2));+ else if (arg_count == 1)+ ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);++ arg_count--;+ word_arg_count--;+ break;+ }++ if (ins != NOP) {+ if (prev_ins != NOP)+ FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));+ prev_ins = ins;+ ins = NOP;+ }++ types >>= SLJIT_DEF_SHIFT;+ }++ types = types_save;+ arg_count = arg_count_save;++ while (types) {+ switch (types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ arg_count--;+ if (offsets[arg_count] == 254)+ ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);+ else if (offsets[arg_count] < 16)+ ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]);+ break;+ case SLJIT_ARG_TYPE_F64:+ arg_count--;+ if (offsets[arg_count] == 254)+ ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);+ else if (offsets[arg_count] < 16) {+ if (prev_ins != NOP)+ FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));+ prev_ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]);+ ins = LW | S(SLJIT_SP) | TA(5 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count] + sizeof(sljit_sw));+ }+ break;+ default:+ arg_count--;+ break;+ }++ if (ins != NOP) {+ if (prev_ins != NOP)+ FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));+ prev_ins = ins;+ ins = NOP;+ }++ types >>= SLJIT_DEF_SHIFT;+ }++ *ins_ptr = prev_ins;++ return SLJIT_SUCCESS;+}++static sljit_s32 post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)+{+ sljit_s32 stack_offset = 0;++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ stack_offset += sizeof(sljit_f32);+ break;+ case SLJIT_ARG_TYPE_F64:+ if (stack_offset & 0x7)+ stack_offset += sizeof(sljit_sw);+ stack_offset += sizeof(sljit_f64);+ break;+ default:+ stack_offset += sizeof(sljit_sw);+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */+ if (stack_offset > 16)+ return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(16), DR(SLJIT_SP));++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ struct sljit_jump *jump;+ sljit_ins ins;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));++ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);++ PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));++ jump->flags |= IS_JAL | IS_CALL;+ PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));+ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));++ PTR_FAIL_IF(post_call_with_args(compiler, arg_types));++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);++ if (src & SLJIT_IMM)+ FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));+ else if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));+ else if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));+ }++ FAIL_IF(call_with_args(compiler, arg_types, &ins));++ /* Register input. */+ FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));+ return post_call_with_args(compiler, arg_types);+}
+ src/c/pcre2/src/sljit/sljitNativeMIPS_64.c view
@@ -0,0 +1,672 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/* mips 64-bit arch dependent functions. */++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)+{+ sljit_s32 shift = 32;+ sljit_s32 shift2;+ sljit_s32 inv = 0;+ sljit_ins ins;+ sljit_uw uimm;++ if (!(imm & ~0xffff))+ return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);++ if (imm < 0 && imm >= SIMM_MIN)+ return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);++ if (imm <= 0x7fffffffl && imm >= -0x80000000l) {+ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));+ return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;+ }++ /* Zero extended number. */+ uimm = imm;+ if (imm < 0) {+ uimm = ~imm;+ inv = 1;+ }++ while (!(uimm & 0xff00000000000000l)) {+ shift -= 8;+ uimm <<= 8;+ }++ if (!(uimm & 0xf000000000000000l)) {+ shift -= 4;+ uimm <<= 4;+ }++ if (!(uimm & 0xc000000000000000l)) {+ shift -= 2;+ uimm <<= 2;+ }++ if ((sljit_sw)uimm < 0) {+ uimm >>= 1;+ shift += 1;+ }+ SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));++ if (inv)+ uimm = ~uimm;++ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));+ if (uimm & 0x0000ffff00000000l)+ FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));++ imm &= (1l << shift) - 1;+ if (!(imm & ~0xffff)) {+ ins = (shift == 32) ? DSLL32 : DSLL;+ if (shift < 32)+ ins |= SH_IMM(shift);+ FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));+ return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);+ }++ /* Double shifts needs to be performed. */+ uimm <<= 32;+ shift2 = shift - 16;++ while (!(uimm & 0xf000000000000000l)) {+ shift2 -= 4;+ uimm <<= 4;+ }++ if (!(uimm & 0xc000000000000000l)) {+ shift2 -= 2;+ uimm <<= 2;+ }++ if (!(uimm & 0x8000000000000000l)) {+ shift2--;+ uimm <<= 1;+ }++ SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));++ FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));+ FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));+ FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));++ imm &= (1l << shift2) - 1;+ return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);+}++#define SELECT_OP(a, b) \+ (!(op & SLJIT_I32_OP) ? a : b)++#define EMIT_LOGICAL(op_imm, op_norm) \+ if (flags & SRC2_IMM) { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \+ } \+ else { \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \+ }++#define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \+ if (flags & SRC2_IMM) { \+ if (src2 >= 32) { \+ SLJIT_ASSERT(!(op & SLJIT_I32_OP)); \+ ins = op_dimm32; \+ src2 -= 32; \+ } \+ else \+ ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \+ } \+ else { \+ ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \+ if (!(flags & UNUSED_DEST)) \+ FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \+ }++static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,+ sljit_s32 dst, sljit_s32 src1, sljit_sw src2)+{+ sljit_ins ins;+ sljit_s32 is_overflow, is_carry, is_handled;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if (dst != src2)+ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S8) {+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));+ return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));+ }+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));+ }+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S16) {+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));+ return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));+ }+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));+ }+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U32:+ SLJIT_ASSERT(!(op & SLJIT_I32_OP));+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));+ return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));++ case SLJIT_MOV_S32:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));++ case SLJIT_NOT:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ if (!(flags & UNUSED_DEST))+ FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));+ return SLJIT_SUCCESS;++ case SLJIT_CLZ:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));+ if (!(flags & UNUSED_DEST))+ FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));+#else /* SLJIT_MIPS_REV < 1 */+ if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));+ return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);+ }+ /* Nearly all instructions are unmovable in the following sequence. */+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));+ /* Check zero. */+ FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_I32_OP) ? 32 : 64), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));+ /* Loop for searching the highest bit. */+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));+ FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));+#endif /* SLJIT_MIPS_REV >= 1 */+ return SLJIT_SUCCESS;++ case SLJIT_ADD:+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));+ else+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));+ }+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));++ if (is_overflow || is_carry) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ else {+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ }+ }+ /* dst may be the same as src1 or src2. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));+ }+ else {+ if (is_overflow)+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));++ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));+ /* dst may be the same as src1 or src2. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));+ }++ /* a + b >= a | b (otherwise, the carry should be set to 1). */+ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ if (!is_overflow)+ return SLJIT_SUCCESS;+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));+ return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);++ case SLJIT_ADDC:+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);++ if (flags & SRC2_IMM) {+ if (is_carry) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));+ else {+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));+ }+ }+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));+ } else {+ if (is_carry)+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ /* dst may be the same as src1 or src2. */+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));+ }+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));++ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));+ if (!is_carry)+ return SLJIT_SUCCESS;++ /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ /* Set carry flag. */+ return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);++ case SLJIT_SUB:+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ is_handled = 0;++ if (flags & SRC2_IMM) {+ if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ is_handled = 1;+ }+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {+ FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ is_handled = 1;+ }+ }++ if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {+ is_handled = 1;++ if (flags & SRC2_IMM) {+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));+ }+ else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)+ {+ FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));+ }+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {+ FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));+ }+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)+ {+ FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));+ }+ }++ if (is_handled) {+ if (flags & SRC2_IMM) {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));+ if (!(flags & UNUSED_DEST))+ return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));+ }+ else {+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ if (!(flags & UNUSED_DEST))+ return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));+ }+ return SLJIT_SUCCESS;+ }++ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;+ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0)+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));+ else+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));+ }+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));++ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));+ /* dst may be the same as src1 or src2. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));+ }+ else {+ if (is_overflow)+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ else if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));++ if (is_overflow || is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));+ /* dst may be the same as src1 or src2. */+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));+ }++ if (!is_overflow)+ return SLJIT_SUCCESS;+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));+ if (op & SLJIT_SET_Z)+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));+ return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);++ case SLJIT_SUBC:+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);++ if (flags & SRC2_IMM) {+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));+ /* dst may be the same as src1 or src2. */+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));+ }+ else {+ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+ /* dst may be the same as src1 or src2. */+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));+ }++ if (is_carry)+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));++ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));+ return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;++ case SLJIT_MUL:+ SLJIT_ASSERT(!(flags & SRC2_IMM));++ if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));+#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ if (op & SLJIT_I32_OP)+ return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));+ FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));+ return push_inst(compiler, MFLO | D(dst), DR(dst));+#else /* SLJIT_MIPS_REV < 1 */+ FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));+ return push_inst(compiler, MFLO | D(dst), DR(dst));+#endif /* SLJIT_MIPS_REV >= 6 */+ }++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));+ FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));+#else /* SLJIT_MIPS_REV < 6 */+ FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));+ FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));+ FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));+#endif /* SLJIT_MIPS_REV >= 6 */+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));+ return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);++ case SLJIT_AND:+ EMIT_LOGICAL(ANDI, AND);+ return SLJIT_SUCCESS;++ case SLJIT_OR:+ EMIT_LOGICAL(ORI, OR);+ return SLJIT_SUCCESS;++ case SLJIT_XOR:+ EMIT_LOGICAL(XORI, XOR);+ return SLJIT_SUCCESS;++ case SLJIT_SHL:+ EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);+ return SLJIT_SUCCESS;++ case SLJIT_LSHR:+ EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);+ return SLJIT_SUCCESS;++ case SLJIT_ASHR:+ EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);+ return SLJIT_SUCCESS;+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)+{+ FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));+ FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));+ FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));+ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ sljit_ins *inst = (sljit_ins *)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 0);+ inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);+ inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);+ inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);+ inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 6);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, new_constant, executable_offset);+}++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)+{+ sljit_s32 arg_count = 0;+ sljit_s32 word_arg_count = 0;+ sljit_s32 float_arg_count = 0;+ sljit_s32 types = 0;+ sljit_ins prev_ins = NOP;+ sljit_ins ins = NOP;++ SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);++ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ case SLJIT_ARG_TYPE_F64:+ arg_count++;+ float_arg_count++;+ break;+ default:+ arg_count++;+ word_arg_count++;+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ while (types) {+ switch (types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ if (arg_count != float_arg_count)+ ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count);+ else if (arg_count == 1)+ ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);+ arg_count--;+ float_arg_count--;+ break;+ case SLJIT_ARG_TYPE_F64:+ if (arg_count != float_arg_count)+ ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count);+ else if (arg_count == 1)+ ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);+ arg_count--;+ float_arg_count--;+ break;+ default:+ if (arg_count != word_arg_count)+ ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);+ else if (arg_count == 1)+ ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4);+ arg_count--;+ word_arg_count--;+ break;+ }++ if (ins != NOP) {+ if (prev_ins != NOP)+ FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));+ prev_ins = ins;+ ins = NOP;+ }++ types >>= SLJIT_DEF_SHIFT;+ }++ *ins_ptr = prev_ins;++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ struct sljit_jump *jump;+ sljit_ins ins;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));++ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);++ PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));++ jump->flags |= IS_JAL | IS_CALL;+ PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));+ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);++ if (src & SLJIT_IMM)+ FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));+ else if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));+ else if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));+ }++ FAIL_IF(call_with_args(compiler, arg_types, &ins));++ /* Register input. */+ FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));+ return push_inst(compiler, ins, UNMOVABLE_INS);+}
+ src/c/pcre2/src/sljit/sljitNativeMIPS_common.c view
@@ -0,0 +1,2305 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/* Latest MIPS architecture. */++#ifndef __mips_hard_float+/* Disable automatic detection, covers both -msoft-float and -mno-float */+#undef SLJIT_IS_FPU_AVAILABLE+#define SLJIT_IS_FPU_AVAILABLE 0+#endif++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ return "MIPS32-R6" SLJIT_CPUINFO;+#else /* !SLJIT_CONFIG_MIPS_32 */+ return "MIPS64-R6" SLJIT_CPUINFO;+#endif /* SLJIT_CONFIG_MIPS_32 */++#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ return "MIPS32-R1" SLJIT_CPUINFO;+#else /* !SLJIT_CONFIG_MIPS_32 */+ return "MIPS64-R1" SLJIT_CPUINFO;+#endif /* SLJIT_CONFIG_MIPS_32 */++#else /* SLJIT_MIPS_REV < 1 */+ return "MIPS III" SLJIT_CPUINFO;+#endif /* SLJIT_MIPS_REV >= 6 */+}++/* Length of an instruction word+ Both for mips-32 and mips-64 */+typedef sljit_u32 sljit_ins;++#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)+#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)++/* For position independent code, t9 must contain the function address. */+#define PIC_ADDR_REG TMP_REG2++/* Floating point status register. */+#define FCSR_REG 31+/* Return address register. */+#define RETURN_ADDR_REG 31++/* Flags are kept in volatile registers. */+#define EQUAL_FLAG 3+#define OTHER_FLAG 1++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)+#define TMP_FREG3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3)++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {+ 0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 4, 25, 31+};++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {+ 0, 0, 14, 2, 4, 6, 8, 12, 10, 16+};++#else++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {+ 0, 0, 13, 14, 15, 16, 17, 12, 18, 10+};++#endif++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++#define S(s) (reg_map[s] << 21)+#define T(t) (reg_map[t] << 16)+#define D(d) (reg_map[d] << 11)+#define FT(t) (freg_map[t] << 16)+#define FS(s) (freg_map[s] << 11)+#define FD(d) (freg_map[d] << 6)+/* Absolute registers. */+#define SA(s) ((s) << 21)+#define TA(t) ((t) << 16)+#define DA(d) ((d) << 11)+#define IMM(imm) ((imm) & 0xffff)+#define SH_IMM(imm) ((imm) << 6)++#define DR(dr) (reg_map[dr])+#define FR(dr) (freg_map[dr])+#define HI(opcode) ((opcode) << 26)+#define LO(opcode) (opcode)+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+/* CMP.cond.fmt */+/* S = (20 << 21) D = (21 << 21) */+#define CMP_FMT_S (20 << 21)+#endif /* SLJIT_MIPS_REV >= 6 */+/* S = (16 << 21) D = (17 << 21) */+#define FMT_S (16 << 21)+#define FMT_D (17 << 21)++#define ABS_S (HI(17) | FMT_S | LO(5))+#define ADD_S (HI(17) | FMT_S | LO(0))+#define ADDIU (HI(9))+#define ADDU (HI(0) | LO(33))+#define AND (HI(0) | LO(36))+#define ANDI (HI(12))+#define B (HI(4))+#define BAL (HI(1) | (17 << 16))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3))+#define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3))+#else /* SLJIT_MIPS_REV < 6 */+#define BC1F (HI(17) | (8 << 21))+#define BC1T (HI(17) | (8 << 21) | (1 << 16))+#endif /* SLJIT_MIPS_REV >= 6 */+#define BEQ (HI(4))+#define BGEZ (HI(1) | (1 << 16))+#define BGTZ (HI(7))+#define BLEZ (HI(6))+#define BLTZ (HI(1) | (0 << 16))+#define BNE (HI(5))+#define BREAK (HI(0) | LO(13))+#define CFC1 (HI(17) | (2 << 21))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3))+#define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))+#define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))+#define C_UN_S (HI(17) | CMP_FMT_S | LO(1))+#define C_FD (FD(TMP_FREG3))+#else /* SLJIT_MIPS_REV < 6 */+#define C_UEQ_S (HI(17) | FMT_S | LO(51))+#define C_ULE_S (HI(17) | FMT_S | LO(55))+#define C_ULT_S (HI(17) | FMT_S | LO(53))+#define C_UN_S (HI(17) | FMT_S | LO(49))+#define C_FD (0)+#endif /* SLJIT_MIPS_REV >= 6 */+#define CVT_S_S (HI(17) | FMT_S | LO(32))+#define DADDIU (HI(25))+#define DADDU (HI(0) | LO(45))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define DDIV (HI(0) | (2 << 6) | LO(30))+#define DDIVU (HI(0) | (2 << 6) | LO(31))+#define DMOD (HI(0) | (3 << 6) | LO(30))+#define DMODU (HI(0) | (3 << 6) | LO(31))+#define DIV (HI(0) | (2 << 6) | LO(26))+#define DIVU (HI(0) | (2 << 6) | LO(27))+#define DMUH (HI(0) | (3 << 6) | LO(28))+#define DMUHU (HI(0) | (3 << 6) | LO(29))+#define DMUL (HI(0) | (2 << 6) | LO(28))+#define DMULU (HI(0) | (2 << 6) | LO(29))+#else /* SLJIT_MIPS_REV < 6 */+#define DDIV (HI(0) | LO(30))+#define DDIVU (HI(0) | LO(31))+#define DIV (HI(0) | LO(26))+#define DIVU (HI(0) | LO(27))+#define DMULT (HI(0) | LO(28))+#define DMULTU (HI(0) | LO(29))+#endif /* SLJIT_MIPS_REV >= 6 */+#define DIV_S (HI(17) | FMT_S | LO(3))+#define DSLL (HI(0) | LO(56))+#define DSLL32 (HI(0) | LO(60))+#define DSLLV (HI(0) | LO(20))+#define DSRA (HI(0) | LO(59))+#define DSRA32 (HI(0) | LO(63))+#define DSRAV (HI(0) | LO(23))+#define DSRL (HI(0) | LO(58))+#define DSRL32 (HI(0) | LO(62))+#define DSRLV (HI(0) | LO(22))+#define DSUBU (HI(0) | LO(47))+#define J (HI(2))+#define JAL (HI(3))+#define JALR (HI(0) | LO(9))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define JR (HI(0) | LO(9))+#else /* SLJIT_MIPS_REV < 6 */+#define JR (HI(0) | LO(8))+#endif /* SLJIT_MIPS_REV >= 6 */+#define LD (HI(55))+#define LUI (HI(15))+#define LW (HI(35))+#define MFC1 (HI(17))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define MOD (HI(0) | (3 << 6) | LO(26))+#define MODU (HI(0) | (3 << 6) | LO(27))+#else /* SLJIT_MIPS_REV < 6 */+#define MFHI (HI(0) | LO(16))+#define MFLO (HI(0) | LO(18))+#endif /* SLJIT_MIPS_REV >= 6 */+#define MOV_S (HI(17) | FMT_S | LO(6))+#define MTC1 (HI(17) | (4 << 21))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define MUH (HI(0) | (3 << 6) | LO(24))+#define MUHU (HI(0) | (3 << 6) | LO(25))+#define MUL (HI(0) | (2 << 6) | LO(24))+#define MULU (HI(0) | (2 << 6) | LO(25))+#else /* SLJIT_MIPS_REV < 6 */+#define MULT (HI(0) | LO(24))+#define MULTU (HI(0) | LO(25))+#endif /* SLJIT_MIPS_REV >= 6 */+#define MUL_S (HI(17) | FMT_S | LO(2))+#define NEG_S (HI(17) | FMT_S | LO(7))+#define NOP (HI(0) | LO(0))+#define NOR (HI(0) | LO(39))+#define OR (HI(0) | LO(37))+#define ORI (HI(13))+#define SD (HI(63))+#define SDC1 (HI(61))+#define SLT (HI(0) | LO(42))+#define SLTI (HI(10))+#define SLTIU (HI(11))+#define SLTU (HI(0) | LO(43))+#define SLL (HI(0) | LO(0))+#define SLLV (HI(0) | LO(4))+#define SRL (HI(0) | LO(2))+#define SRLV (HI(0) | LO(6))+#define SRA (HI(0) | LO(3))+#define SRAV (HI(0) | LO(7))+#define SUB_S (HI(17) | FMT_S | LO(1))+#define SUBU (HI(0) | LO(35))+#define SW (HI(43))+#define SWC1 (HI(57))+#define TRUNC_W_S (HI(17) | FMT_S | LO(13))+#define XOR (HI(0) | LO(38))+#define XORI (HI(14))++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+#define CLZ (HI(28) | LO(32))+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#define DCLZ (LO(18))+#else /* SLJIT_MIPS_REV < 6 */+#define DCLZ (HI(28) | LO(36))+#define MOVF (HI(0) | (0 << 16) | LO(1))+#define MOVN (HI(0) | LO(11))+#define MOVT (HI(0) | (1 << 16) | LO(1))+#define MOVZ (HI(0) | LO(10))+#define MUL (HI(28) | LO(2))+#endif /* SLJIT_MIPS_REV >= 6 */+#define PREF (HI(51))+#define PREFX (HI(19) | LO(15))+#define SEB (HI(31) | (16 << 6) | LO(32))+#define SEH (HI(31) | (24 << 6) | LO(32))+#endif /* SLJIT_MIPS_REV >= 1 */++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define ADDU_W ADDU+#define ADDIU_W ADDIU+#define SLL_W SLL+#define SUBU_W SUBU+#else+#define ADDU_W DADDU+#define ADDIU_W DADDIU+#define SLL_W DSLL+#define SUBU_W DSUBU+#endif++#define SIMM_MAX (0x7fff)+#define SIMM_MIN (-0x8000)+#define UIMM_MAX (0xffff)++/* dest_reg is the absolute name of the register+ Useful for reordering instructions in the delay slot. */+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)+{+ sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS+ || delay_slot == ((ins >> 11) & 0x1f) || delay_slot == ((ins >> 16) & 0x1f));+ FAIL_IF(!ptr);+ *ptr = ins;+ compiler->size++;+ compiler->delay_slot = delay_slot;+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_ins invert_branch(sljit_s32 flags)+{+ if (flags & IS_BIT26_COND)+ return (1 << 26);+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ if (flags & IS_BIT23_COND)+ return (1 << 23);+#endif /* SLJIT_MIPS_REV >= 6 */+ return (1 << 16);+}++static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_sw diff;+ sljit_uw target_addr;+ sljit_ins *inst;+ sljit_ins saved_inst;++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))+ return code_ptr;+#else+ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ return code_ptr;+#endif++ if (jump->flags & JUMP_ADDR)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;+ }++ inst = (sljit_ins *)jump->addr;+ if (jump->flags & IS_COND)+ inst--;++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (jump->flags & IS_CALL)+ goto keep_address;+#endif++ /* B instructions. */+ if (jump->flags & IS_MOVABLE) {+ diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;+ if (diff <= SIMM_MAX && diff >= SIMM_MIN) {+ jump->flags |= PATCH_B;++ if (!(jump->flags & IS_COND)) {+ inst[0] = inst[-1];+ inst[-1] = (jump->flags & IS_JAL) ? BAL : B;+ jump->addr -= sizeof(sljit_ins);+ return inst;+ }+ saved_inst = inst[0];+ inst[0] = inst[-1];+ inst[-1] = saved_inst ^ invert_branch(jump->flags);+ jump->addr -= 2 * sizeof(sljit_ins);+ return inst;+ }+ }+ else {+ diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;+ if (diff <= SIMM_MAX && diff >= SIMM_MIN) {+ jump->flags |= PATCH_B;++ if (!(jump->flags & IS_COND)) {+ inst[0] = (jump->flags & IS_JAL) ? BAL : B;+ inst[1] = NOP;+ return inst + 1;+ }+ inst[0] = inst[0] ^ invert_branch(jump->flags);+ inst[1] = NOP;+ jump->addr -= sizeof(sljit_ins);+ return inst + 1;+ }+ }++ if (jump->flags & IS_COND) {+ if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~0xfffffff)) {+ jump->flags |= PATCH_J;+ saved_inst = inst[0];+ inst[0] = inst[-1];+ inst[-1] = (saved_inst & 0xffff0000) | 3;+ inst[1] = J;+ inst[2] = NOP;+ return inst + 2;+ }+ else if ((target_addr & ~0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~0xfffffff)) {+ jump->flags |= PATCH_J;+ inst[0] = (inst[0] & 0xffff0000) | 3;+ inst[1] = NOP;+ inst[2] = J;+ inst[3] = NOP;+ jump->addr += sizeof(sljit_ins);+ return inst + 3;+ }+ }+ else {+ /* J instuctions. */+ if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == (jump->addr & ~0xfffffff)) {+ jump->flags |= PATCH_J;+ inst[0] = inst[-1];+ inst[-1] = (jump->flags & IS_JAL) ? JAL : J;+ jump->addr -= sizeof(sljit_ins);+ return inst;+ }++ if ((target_addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)) {+ jump->flags |= PATCH_J;+ inst[0] = (jump->flags & IS_JAL) ? JAL : J;+ inst[1] = NOP;+ return inst + 1;+ }+ }++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+keep_address:+ if (target_addr <= 0x7fffffff) {+ jump->flags |= PATCH_ABS32;+ if (jump->flags & IS_COND) {+ inst[0] -= 4;+ inst++;+ }+ inst[2] = inst[6];+ inst[3] = inst[7];+ return inst + 3;+ }+ if (target_addr <= 0x7fffffffffffl) {+ jump->flags |= PATCH_ABS48;+ if (jump->flags & IS_COND) {+ inst[0] -= 2;+ inst++;+ }+ inst[4] = inst[6];+ inst[5] = inst[7];+ return inst + 5;+ }+#endif++ return code_ptr;+}++#ifdef __GNUC__+static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)+{+ SLJIT_CACHE_FLUSH(code, code_ptr);+}+#endif++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)++static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)+{+ if (max_label < 0x80000000l) {+ put_label->flags = 0;+ return 1;+ }++ if (max_label < 0x800000000000l) {+ put_label->flags = 1;+ return 3;+ }++ put_label->flags = 2;+ return 5;+}++static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)+{+ sljit_uw addr = put_label->label->addr;+ sljit_ins *inst = (sljit_ins *)put_label->addr;+ sljit_s32 reg = *inst;++ if (put_label->flags == 0) {+ SLJIT_ASSERT(addr < 0x80000000l);+ inst[0] = LUI | T(reg) | IMM(addr >> 16);+ }+ else if (put_label->flags == 1) {+ SLJIT_ASSERT(addr < 0x800000000000l);+ inst[0] = LUI | T(reg) | IMM(addr >> 32);+ inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);+ inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);+ inst += 2;+ }+ else {+ inst[0] = LUI | T(reg) | IMM(addr >> 48);+ inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);+ inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);+ inst[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);+ inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);+ inst += 4;+ }++ inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);+}++#endif++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ sljit_uw next_addr;+ sljit_sw executable_offset;+ sljit_uw addr;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ struct sljit_put_label *put_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));+ reverse_buf(compiler);++ code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);+ PTR_FAIL_WITH_EXEC_IF(code);+ buf = compiler->buf;++ code_ptr = code;+ word_count = 0;+ next_addr = 0;+ executable_offset = SLJIT_EXEC_OFFSET(code);++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ put_label = compiler->put_labels;++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+ *code_ptr = *buf_ptr++;+ if (next_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);++ /* These structures are ordered by their address. */+ if (label && label->size == word_count) {+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = code_ptr - code;+ label = label->next;+ }+ if (jump && jump->addr == word_count) {+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ jump->addr = (sljit_uw)(code_ptr - 3);+#else+ jump->addr = (sljit_uw)(code_ptr - 7);+#endif+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);+ jump = jump->next;+ }+ if (const_ && const_->addr == word_count) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ }+ if (put_label && put_label->addr == word_count) {+ SLJIT_ASSERT(put_label->label);+ put_label->addr = (sljit_uw)code_ptr;+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));+ word_count += 5;+#endif+ put_label = put_label->next;+ }+ next_addr = compute_next_addr(label, jump, const_, put_label);+ }+ code_ptr ++;+ word_count ++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->addr = (sljit_uw)code_ptr;+ label->size = code_ptr - code;+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(!put_label);+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);++ jump = compiler->jumps;+ while (jump) {+ do {+ addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;+ buf_ptr = (sljit_ins *)jump->addr;++ if (jump->flags & PATCH_B) {+ addr = (sljit_sw)(addr - ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins))) >> 2;+ SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | (addr & 0xffff);+ break;+ }+ if (jump->flags & PATCH_J) {+ SLJIT_ASSERT((addr & ~0xfffffff) == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~0xfffffff));+ buf_ptr[0] |= (addr >> 2) & 0x03ffffff;+ break;+ }++ /* Set the fields of immediate loads. */+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);+#else+ if (jump->flags & PATCH_ABS32) {+ SLJIT_ASSERT(addr <= 0x7fffffff);+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);+ }+ else if (jump->flags & PATCH_ABS48) {+ SLJIT_ASSERT(addr <= 0x7fffffffffffl);+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);+ buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);+ }+ else {+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);+ buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);+ buf_ptr[5] = (buf_ptr[5] & 0xffff0000) | (addr & 0xffff);+ }+#endif+ } while (0);+ jump = jump->next;+ }++ put_label = compiler->put_labels;+ while (put_label) {+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ addr = put_label->label->addr;+ buf_ptr = (sljit_ins *)put_label->addr;++ SLJIT_ASSERT((buf_ptr[0] & 0xffe00000) == LUI && (buf_ptr[1] & 0xfc000000) == ORI);+ buf_ptr[0] |= (addr >> 16) & 0xffff;+ buf_ptr[1] |= addr & 0xffff;+#else+ put_label_set(put_label);+#endif+ put_label = put_label->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);++ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++#ifndef __GNUC__+ SLJIT_CACHE_FLUSH(code, code_ptr);+#else+ /* GCC workaround for invalid code generation with -O2. */+ sljit_cache_flush(code, code_ptr);+#endif+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ return code;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ sljit_sw fir = 0;++ switch (feature_type) {+ case SLJIT_HAS_FPU:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return SLJIT_IS_FPU_AVAILABLE;+#elif defined(__GNUC__)+ __asm__ ("cfc1 %0, $0" : "=r"(fir));+ return (fir >> 22) & 0x1;+#else+#error "FIR check is not implemented for this architecture"+#endif+ case SLJIT_HAS_ZERO_REGISTER:+ return 1;++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_CMOV:+ case SLJIT_HAS_PREFETCH:+ return 1;+#endif /* SLJIT_MIPS_REV >= 1 */++ default:+ return fir;+ }+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++/* Creates an index in data_transfer_insts array. */+#define LOAD_DATA 0x01+#define WORD_DATA 0x00+#define BYTE_DATA 0x02+#define HALF_DATA 0x04+#define INT_DATA 0x06+#define SIGNED_DATA 0x08+/* Separates integer and floating point registers */+#define GPR_REG 0x0f+#define DOUBLE_DATA 0x10+#define SINGLE_DATA 0x12++#define MEM_MASK 0x1f++#define ARG_TEST 0x00020+#define ALT_KEEP_CACHE 0x00040+#define CUMULATIVE_OP 0x00080+#define LOGICAL_OP 0x00100+#define IMM_OP 0x00200+#define SRC2_IMM 0x00400++#define UNUSED_DEST 0x00800+#define REG_DEST 0x01000+#define REG1_SOURCE 0x02000+#define REG2_SOURCE 0x04000+#define SLOW_SRC1 0x08000+#define SLOW_SRC2 0x10000+#define SLOW_DEST 0x20000++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define STACK_STORE SW+#define STACK_LOAD LW+#else+#define STACK_STORE SD+#define STACK_LOAD LD+#endif++static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#include "sljitNativeMIPS_32.c"+#else+#include "sljitNativeMIPS_64.c"+#endif++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_ins base;+ sljit_s32 args, i, tmp, offs;++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ local_size = (local_size + 15) & ~0xf;+#else+ local_size = (local_size + 31) & ~0x1f;+#endif+ compiler->local_size = local_size;++ if (local_size <= SIMM_MAX) {+ /* Frequent case. */+ FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));+ base = S(SLJIT_SP);+ offs = local_size - (sljit_sw)sizeof(sljit_sw);+ }+ else {+ FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size));+ FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));+ base = S(TMP_REG2);+ local_size = 0;+ offs = -(sljit_sw)sizeof(sljit_sw);+ }++ FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offs), MOVABLE_INS));++ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = SLJIT_S0; i >= tmp; i--) {+ offs -= (sljit_s32)(sizeof(sljit_sw));+ FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ offs -= (sljit_s32)(sizeof(sljit_sw));+ FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));+ }++ args = get_arg_count(arg_types);++ if (args >= 1)+ FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_S0), DR(SLJIT_S0)));+ if (args >= 2)+ FAIL_IF(push_inst(compiler, ADDU_W | SA(5) | TA(0) | D(SLJIT_S1), DR(SLJIT_S1)));+ if (args >= 3)+ FAIL_IF(push_inst(compiler, ADDU_W | SA(6) | TA(0) | D(SLJIT_S2), DR(SLJIT_S2)));++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ compiler->local_size = (local_size + 15) & ~0xf;+#else+ compiler->local_size = (local_size + 31) & ~0x1f;+#endif+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 local_size, i, tmp, offs;+ sljit_ins base;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));++ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));++ local_size = compiler->local_size;+ if (local_size <= SIMM_MAX)+ base = S(SLJIT_SP);+ else {+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size));+ FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));+ base = S(TMP_REG1);+ local_size = 0;+ }++ FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - (sljit_s32)sizeof(sljit_sw)), RETURN_ADDR_REG));+ offs = local_size - (sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);++ tmp = compiler->scratches;+ for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {+ FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i)));+ offs += (sljit_s32)(sizeof(sljit_sw));+ }++ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = tmp; i <= SLJIT_S0; i++) {+ FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i)));+ offs += (sljit_s32)(sizeof(sljit_sw));+ }++ SLJIT_ASSERT(offs == local_size - (sljit_sw)(sizeof(sljit_sw)));++ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));+ if (compiler->local_size <= SIMM_MAX)+ return push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(compiler->local_size), UNMOVABLE_INS);+ else+ return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_SP), UNMOVABLE_INS);+}++#undef STACK_STORE+#undef STACK_LOAD++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define ARCH_32_64(a, b) a+#else+#define ARCH_32_64(a, b) b+#endif++static const sljit_ins data_transfer_insts[16 + 4] = {+/* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),+/* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),+/* u b s */ HI(40) /* sb */,+/* u b l */ HI(36) /* lbu */,+/* u h s */ HI(41) /* sh */,+/* u h l */ HI(37) /* lhu */,+/* u i s */ HI(43) /* sw */,+/* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),++/* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),+/* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),+/* s b s */ HI(40) /* sb */,+/* s b l */ HI(32) /* lb */,+/* s h s */ HI(41) /* sh */,+/* s h l */ HI(33) /* lh */,+/* s i s */ HI(43) /* sw */,+/* s i l */ HI(35) /* lw */,++/* d s */ HI(61) /* sdc1 */,+/* d l */ HI(53) /* ldc1 */,+/* s s */ HI(57) /* swc1 */,+/* s l */ HI(49) /* lwc1 */,+};++#undef ARCH_32_64++/* reg_ar is an absoulute register! */++/* Can perform an operation using at most 1 instruction. */+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)+{+ SLJIT_ASSERT(arg & SLJIT_MEM);++ if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {+ /* Works for both absoulte and relative addresses. */+ if (SLJIT_UNLIKELY(flags & ARG_TEST))+ return 1;+ FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)+ | TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));+ return -1;+ }+ return 0;+}++/* See getput_arg below.+ Note: can_cache is called only for binary operators. Those+ operators always uses word arguments without write back. */+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)+{+ SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));++ /* Simple operation except for updates. */+ if (arg & OFFS_REG_MASK) {+ argw &= 0x3;+ next_argw &= 0x3;+ if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))+ return 1;+ return 0;+ }++ if (arg == next_arg) {+ if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN))+ return 1;+ return 0;+ }++ return 0;+}++/* Emit the necessary instructions. See can_cache above. */+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)+{+ sljit_s32 tmp_ar, base, delay_slot;++ SLJIT_ASSERT(arg & SLJIT_MEM);+ if (!(next_arg & SLJIT_MEM)) {+ next_arg = 0;+ next_argw = 0;+ }++ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {+ tmp_ar = reg_ar;+ delay_slot = reg_ar;+ }+ else {+ tmp_ar = DR(TMP_REG1);+ delay_slot = MOVABLE_INS;+ }+ base = arg & REG_MASK;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ /* Using the cache. */+ if (argw == compiler->cache_argw) {+ if (arg == compiler->cache_arg)+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);++ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {+ if (arg == next_arg && argw == (next_argw & 0x3)) {+ compiler->cache_arg = arg;+ compiler->cache_argw = argw;+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);+ }+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);+ }+ }++ if (SLJIT_UNLIKELY(argw)) {+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);+ compiler->cache_argw = argw;+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));+ }++ if (arg == next_arg && argw == (next_argw & 0x3)) {+ compiler->cache_arg = arg;+ compiler->cache_argw = argw;+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));+ tmp_ar = DR(TMP_REG3);+ }+ else+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);+ }++ if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {+ if (argw != compiler->cache_argw) {+ FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));+ compiler->cache_argw = argw;+ }+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);+ }++ if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {+ if (argw != compiler->cache_argw)+ FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));+ }+ else {+ compiler->cache_arg = SLJIT_MEM;+ FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));+ }+ compiler->cache_argw = argw;++ if (!base)+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);++ if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {+ compiler->cache_arg = arg;+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);+ }++ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);+}++static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)+{+ sljit_s32 tmp_ar, base, delay_slot;++ if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))+ return compiler->error;++ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {+ tmp_ar = reg_ar;+ delay_slot = reg_ar;+ }+ else {+ tmp_ar = DR(TMP_REG1);+ delay_slot = MOVABLE_INS;+ }+ base = arg & REG_MASK;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ if (SLJIT_UNLIKELY(argw)) {+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));+ }+ else+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);+ }++ FAIL_IF(load_immediate(compiler, tmp_ar, argw));++ if (base != 0)+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));++ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);+}++static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)+{+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))+ return compiler->error;+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);+}++static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ /* arg1 goes to TMP_REG1 or src reg+ arg2 goes to TMP_REG2, imm or src reg+ TMP_REG3 can be used for caching+ result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */+ sljit_s32 dst_r = TMP_REG2;+ sljit_s32 src1_r;+ sljit_sw src2_r = 0;+ sljit_s32 sugg_src2_r = TMP_REG2;++ if (!(flags & ALT_KEEP_CACHE)) {+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+ }++ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {+ SLJIT_ASSERT(HAS_FLAGS(op));+ flags |= UNUSED_DEST;+ }+ else if (FAST_IS_REG(dst)) {+ dst_r = dst;+ flags |= REG_DEST;+ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)+ sugg_src2_r = dst_r;+ }+ else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))+ flags |= SLOW_DEST;++ if (flags & IMM_OP) {+ if ((src2 & SLJIT_IMM) && src2w) {+ if ((!(flags & LOGICAL_OP) && (src2w <= SIMM_MAX && src2w >= SIMM_MIN))+ || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_MAX))) {+ flags |= SRC2_IMM;+ src2_r = src2w;+ }+ }+ if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {+ if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_MAX && src1w >= SIMM_MIN))+ || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_MAX))) {+ flags |= SRC2_IMM;+ src2_r = src1w;++ /* And swap arguments. */+ src1 = src2;+ src1w = src2w;+ src2 = SLJIT_IMM;+ /* src2w = src2_r unneeded. */+ }+ }+ }++ /* Source 1. */+ if (FAST_IS_REG(src1)) {+ src1_r = src1;+ flags |= REG1_SOURCE;+ }+ else if (src1 & SLJIT_IMM) {+ if (src1w) {+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));+ src1_r = TMP_REG1;+ }+ else+ src1_r = 0;+ }+ else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC1;+ src1_r = TMP_REG1;+ }++ /* Source 2. */+ if (FAST_IS_REG(src2)) {+ src2_r = src2;+ flags |= REG2_SOURCE;+ if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)+ dst_r = src2_r;+ }+ else if (src2 & SLJIT_IMM) {+ if (!(flags & SRC2_IMM)) {+ if (src2w) {+ FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w));+ src2_r = sugg_src2_r;+ }+ else {+ src2_r = 0;+ if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM))+ dst_r = 0;+ }+ }+ }+ else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC2;+ src2_r = sugg_src2_r;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ SLJIT_ASSERT(src2_r == TMP_REG2);+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));+ }+ else {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));+ }+ }+ else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w, dst, dstw));++ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));++ if (dst & SLJIT_MEM) {+ if (!(flags & SLOW_DEST)) {+ getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);+ return compiler->error;+ }+ return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ sljit_s32 int_op = op & SLJIT_I32_OP;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ return push_inst(compiler, BREAK, UNMOVABLE_INS);+ case SLJIT_NOP:+ return push_inst(compiler, NOP, UNMOVABLE_INS);+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));+#else /* !SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));+ return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));+#else /* SLJIT_MIPS_REV < 6 */+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));+#else /* !SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));+ return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));+#endif /* SLJIT_MIPS_REV >= 6 */+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIVMOD_SW:+ case SLJIT_DIV_UW:+ case SLJIT_DIV_SW:+ SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (int_op) {+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));+ }+ else {+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));+ }+#else /* !SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));+ return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));+#else /* SLJIT_MIPS_REV < 6 */+#if !(defined SLJIT_MIPS_REV)+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+#endif /* !SLJIT_MIPS_REV */+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (int_op)+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));+ else+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));+#else /* !SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));+ return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));+#endif /* SLJIT_MIPS_REV >= 6 */+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ if (!(src & OFFS_REG_MASK)) {+ if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)+ return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);++ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));+ return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);+ }++ srcw &= 0x3;++ if (SLJIT_UNLIKELY(srcw != 0)) {+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));+ return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);+ }++ return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);+}+#endif /* SLJIT_MIPS_REV >= 1 */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+# define flags 0+#else+ sljit_s32 flags = 0;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT)+ flags |= INT_DATA | SIGNED_DATA;+#endif++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOV_U32:+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);+#else+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);+#endif++ case SLJIT_MOV_S32:+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);+#else+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw);+#endif++ case SLJIT_MOV_U8:+ return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);++ case SLJIT_MOV_S8:+ return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);++ case SLJIT_MOV_U16:+ return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);++ case SLJIT_MOV_S16:+ return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);++ case SLJIT_NOT:+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_NEG:+ return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);++ case SLJIT_CLZ:+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+# undef flags+#endif+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+# define flags 0+#else+ sljit_s32 flags = 0;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))+ return SLJIT_SUCCESS;++#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (op & SLJIT_I32_OP) {+ flags |= INT_DATA | SIGNED_DATA;+ if (src1 & SLJIT_IMM)+ src1w = (sljit_s32)src1w;+ if (src2 & SLJIT_IMM)+ src2w = (sljit_s32)src2w;+ }+#endif++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ case SLJIT_ADDC:+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SUB:+ case SLJIT_SUBC:+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_MUL:+ return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SHL:+ case SLJIT_LSHR:+ case SLJIT_ASHR:+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ if (src2 & SLJIT_IMM)+ src2w &= 0x1f;+#else+ if (src2 & SLJIT_IMM) {+ if (op & SLJIT_I32_OP)+ src2w &= 0x1f;+ else+ src2w &= 0x3f;+ }+#endif+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+# undef flags+#endif+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));++ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));+ return push_inst(compiler, NOP, UNMOVABLE_INS);+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ return emit_prefetch(compiler, src, srcw);+#else /* SLJIT_MIPS_REV < 1 */+ return SLJIT_SUCCESS;+#endif /* SLJIT_MIPS_REV >= 1 */+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(reg));+ return reg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));+ return FR(reg);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))+#define FMT(op) (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) << (21 - 8))++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+# define flags 0+#else+ sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64) << 21;+#endif++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));+ src = TMP_FREG1;+ }++ FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));++ if (FAST_IS_REG(dst))+ return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);++ /* Store the integer value from a VFP register. */+ return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+# undef is_long+#endif+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+# define flags 0+#else+ sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) << 21;+#endif++ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));+ else if (src & SLJIT_MEM) {+ /* Load the integer value into a VFP register. */+ FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));+ }+ else {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)+ srcw = (sljit_s32)srcw;+#endif+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));+ FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));+ }++ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);+ return SLJIT_SUCCESS;++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+# undef flags+#endif+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_ins inst;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));+ src2 = TMP_FREG2;+ }++ switch (GET_FLAG_TYPE(op)) {+ case SLJIT_EQUAL_F64:+ case SLJIT_NOT_EQUAL_F64:+ inst = C_UEQ_S;+ break;+ case SLJIT_LESS_F64:+ case SLJIT_GREATER_EQUAL_F64:+ inst = C_ULT_S;+ break;+ case SLJIT_GREATER_F64:+ case SLJIT_LESS_EQUAL_F64:+ inst = C_ULE_S;+ break;+ default:+ SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED_F64 || GET_FLAG_TYPE(op) == SLJIT_ORDERED_F64);+ inst = C_UN_S;+ break;+ }+ return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r;++ CHECK_ERROR();+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)+ op ^= SLJIT_F32_OP;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (dst_r != TMP_FREG1)+ FAIL_IF(push_inst(compiler, MOV_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ FAIL_IF(push_inst(compiler, CVT_S_S | ((op & SLJIT_F32_OP) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));+ op ^= SLJIT_F32_OP;+ break;+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 dst_r, flags = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;++ if (src1 & SLJIT_MEM) {+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {+ FAIL_IF(compiler->error);+ src1 = TMP_FREG1;+ } else+ flags |= SLOW_SRC1;+ }++ if (src2 & SLJIT_MEM) {+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {+ FAIL_IF(compiler->error);+ src2 = TMP_FREG2;+ } else+ flags |= SLOW_SRC2;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));+ }+ else {+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));+ }+ }+ else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));++ if (flags & SLOW_SRC1)+ src1 = TMP_FREG1;+ if (flags & SLOW_SRC2)+ src2 = TMP_FREG2;++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));+ break;++ case SLJIT_SUB_F64:+ FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));+ break;++ case SLJIT_MUL_F64:+ FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));+ break;++ case SLJIT_DIV_F64:+ FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));+ break;+ }++ if (dst_r == TMP_FREG2)+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));++ return SLJIT_SUCCESS;+}++/* --------------------------------------------------------------------- */+/* Other instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ if (FAST_IS_REG(dst))+ return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);++ /* Memory. */+ FAIL_IF(emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw));+ compiler->delay_slot = UNMOVABLE_INS;+ return SLJIT_SUCCESS;+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ compiler->delay_slot = UNMOVABLE_INS;+ return label;+}++#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define JUMP_LENGTH 4+#else+#define JUMP_LENGTH 8+#endif++#define BR_Z(src) \+ inst = BEQ | SA(src) | TA(0) | JUMP_LENGTH; \+ flags = IS_BIT26_COND; \+ delay_check = src;++#define BR_NZ(src) \+ inst = BNE | SA(src) | TA(0) | JUMP_LENGTH; \+ flags = IS_BIT26_COND; \+ delay_check = src;++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)++#define BR_T() \+ inst = BC1NEZ; \+ flags = IS_BIT23_COND; \+ delay_check = FCSR_FCC;+#define BR_F() \+ inst = BC1EQZ; \+ flags = IS_BIT23_COND; \+ delay_check = FCSR_FCC;++#else /* SLJIT_MIPS_REV < 6 */++#define BR_T() \+ inst = BC1T | JUMP_LENGTH; \+ flags = IS_BIT16_COND; \+ delay_check = FCSR_FCC;+#define BR_F() \+ inst = BC1F | JUMP_LENGTH; \+ flags = IS_BIT16_COND; \+ delay_check = FCSR_FCC;++#endif /* SLJIT_MIPS_REV >= 6 */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;+ sljit_ins inst;+ sljit_s32 flags = 0;+ sljit_s32 delay_check = UNMOVABLE_INS;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ switch (type) {+ case SLJIT_EQUAL:+ BR_NZ(EQUAL_FLAG);+ break;+ case SLJIT_NOT_EQUAL:+ BR_Z(EQUAL_FLAG);+ break;+ case SLJIT_LESS:+ case SLJIT_GREATER:+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_GREATER:+ case SLJIT_OVERFLOW:+ case SLJIT_MUL_OVERFLOW:+ BR_Z(OTHER_FLAG);+ break;+ case SLJIT_GREATER_EQUAL:+ case SLJIT_LESS_EQUAL:+ case SLJIT_SIG_GREATER_EQUAL:+ case SLJIT_SIG_LESS_EQUAL:+ case SLJIT_NOT_OVERFLOW:+ case SLJIT_MUL_NOT_OVERFLOW:+ BR_NZ(OTHER_FLAG);+ break;+ case SLJIT_NOT_EQUAL_F64:+ case SLJIT_GREATER_EQUAL_F64:+ case SLJIT_GREATER_F64:+ case SLJIT_ORDERED_F64:+ BR_T();+ break;+ case SLJIT_EQUAL_F64:+ case SLJIT_LESS_F64:+ case SLJIT_LESS_EQUAL_F64:+ case SLJIT_UNORDERED_F64:+ BR_F();+ break;+ default:+ /* Not conditional branch. */+ inst = 0;+ break;+ }++ jump->flags |= flags;+ if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))+ jump->flags |= IS_MOVABLE;++ if (inst)+ PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));++ PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));++ if (type <= SLJIT_JUMP)+ PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));+ else {+ jump->flags |= IS_JAL;+ PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));+ }++ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+ return jump;+}++#define RESOLVE_IMM1() \+ if (src1 & SLJIT_IMM) { \+ if (src1w) { \+ PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \+ src1 = TMP_REG1; \+ } \+ else \+ src1 = 0; \+ }++#define RESOLVE_IMM2() \+ if (src2 & SLJIT_IMM) { \+ if (src2w) { \+ PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \+ src2 = TMP_REG2; \+ } \+ else \+ src2 = 0; \+ }++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ struct sljit_jump *jump;+ sljit_s32 flags;+ sljit_ins inst;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+ flags = ((type & SLJIT_I32_OP) ? INT_DATA : WORD_DATA) | LOAD_DATA;+ if (src1 & SLJIT_MEM) {+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));+ src1 = TMP_REG1;+ }+ if (src2 & SLJIT_MEM) {+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0));+ src2 = TMP_REG2;+ }++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ if (type <= SLJIT_NOT_EQUAL) {+ RESOLVE_IMM1();+ RESOLVE_IMM2();+ jump->flags |= IS_BIT26_COND;+ if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))+ jump->flags |= IS_MOVABLE;+ PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | JUMP_LENGTH, UNMOVABLE_INS));+ }+ else if (type >= SLJIT_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) {+ inst = NOP;+ if ((src1 & SLJIT_IMM) && (src1w == 0)) {+ RESOLVE_IMM2();+ switch (type) {+ case SLJIT_SIG_LESS:+ inst = BLEZ;+ jump->flags |= IS_BIT26_COND;+ break;+ case SLJIT_SIG_GREATER_EQUAL:+ inst = BGTZ;+ jump->flags |= IS_BIT26_COND;+ break;+ case SLJIT_SIG_GREATER:+ inst = BGEZ;+ jump->flags |= IS_BIT16_COND;+ break;+ case SLJIT_SIG_LESS_EQUAL:+ inst = BLTZ;+ jump->flags |= IS_BIT16_COND;+ break;+ }+ src1 = src2;+ }+ else {+ RESOLVE_IMM1();+ switch (type) {+ case SLJIT_SIG_LESS:+ inst = BGEZ;+ jump->flags |= IS_BIT16_COND;+ break;+ case SLJIT_SIG_GREATER_EQUAL:+ inst = BLTZ;+ jump->flags |= IS_BIT16_COND;+ break;+ case SLJIT_SIG_GREATER:+ inst = BLEZ;+ jump->flags |= IS_BIT26_COND;+ break;+ case SLJIT_SIG_LESS_EQUAL:+ inst = BGTZ;+ jump->flags |= IS_BIT26_COND;+ break;+ }+ }+ PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | JUMP_LENGTH, UNMOVABLE_INS));+ }+ else {+ if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {+ RESOLVE_IMM1();+ if ((src2 & SLJIT_IMM) && src2w <= SIMM_MAX && src2w >= SIMM_MIN)+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));+ else {+ RESOLVE_IMM2();+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));+ }+ type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;+ }+ else {+ RESOLVE_IMM2();+ if ((src1 & SLJIT_IMM) && src1w <= SIMM_MAX && src1w >= SIMM_MIN)+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));+ else {+ RESOLVE_IMM1();+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));+ }+ type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;+ }++ jump->flags |= IS_BIT26_COND;+ PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | JUMP_LENGTH, UNMOVABLE_INS));+ }++ PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));+ PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));+ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+ return jump;+}++#undef RESOLVE_IMM1+#undef RESOLVE_IMM2++#undef JUMP_LENGTH+#undef BR_Z+#undef BR_NZ+#undef BR_T+#undef BR_F++#undef FLOAT_DATA+#undef FMT++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ struct sljit_jump *jump = NULL;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ if (src & SLJIT_IMM) {+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));+ jump->u.target = srcw;++ if (compiler->delay_slot != UNMOVABLE_INS)+ jump->flags |= IS_MOVABLE;++ FAIL_IF(emit_const(compiler, TMP_REG2, 0));+ src = TMP_REG2;+ }+ else if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw));+ src = TMP_REG2;+ }++ FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));+ if (jump)+ jump->addr = compiler->size;+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 type)+{+ sljit_s32 src_ar, dst_ar;+ sljit_s32 saved_op = op;+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ sljit_s32 mem_type = WORD_DATA;+#else+ sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ op = GET_OPCODE(op);+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (op == SLJIT_MOV_S32)+ mem_type = INT_DATA | SIGNED_DATA;+#endif+ dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));++ switch (type & 0xff) {+ case SLJIT_EQUAL:+ case SLJIT_NOT_EQUAL:+ FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));+ src_ar = dst_ar;+ break;+ case SLJIT_MUL_OVERFLOW:+ case SLJIT_MUL_NOT_OVERFLOW:+ FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));+ src_ar = dst_ar;+ type ^= 0x1; /* Flip type bit for the XORI below. */+ break;+ case SLJIT_GREATER_F64:+ case SLJIT_LESS_EQUAL_F64:+ type ^= 0x1; /* Flip type bit for the XORI below. */+ case SLJIT_EQUAL_F64:+ case SLJIT_NOT_EQUAL_F64:+ case SLJIT_LESS_F64:+ case SLJIT_GREATER_EQUAL_F64:+ case SLJIT_UNORDERED_F64:+ case SLJIT_ORDERED_F64:+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)+ FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));+#else /* SLJIT_MIPS_REV < 6 */+ FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));+#endif /* SLJIT_MIPS_REV >= 6 */+ FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));+ FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));+ src_ar = dst_ar;+ break;++ default:+ src_ar = OTHER_FLAG;+ break;+ }++ if (type & 0x1) {+ FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));+ src_ar = dst_ar;+ }++ if (op < SLJIT_ADD) {+ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);++ if (src_ar != dst_ar)+ return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);+ return SLJIT_SUCCESS;+ }++ /* OTHER_FLAG cannot be specified as src2 argument at the moment. */+ if (DR(TMP_REG2) != src_ar)+ FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));++ mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;++ if (dst & SLJIT_MEM)+ return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);+ return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ sljit_ins ins;+#endif /* SLJIT_MIPS_REV >= 1 */++ CHECK_ERROR();+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));++#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)++ if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (dst_reg & SLJIT_I32_OP)+ srcw = (sljit_s32)srcw;+#endif+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));+ src = TMP_REG1;+ srcw = 0;+ }++ dst_reg &= ~SLJIT_I32_OP;++ switch (type & 0xff) {+ case SLJIT_EQUAL:+ ins = MOVZ | TA(EQUAL_FLAG);+ break;+ case SLJIT_NOT_EQUAL:+ ins = MOVN | TA(EQUAL_FLAG);+ break;+ case SLJIT_LESS:+ case SLJIT_GREATER:+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_GREATER:+ case SLJIT_OVERFLOW:+ case SLJIT_MUL_OVERFLOW:+ ins = MOVN | TA(OTHER_FLAG);+ break;+ case SLJIT_GREATER_EQUAL:+ case SLJIT_LESS_EQUAL:+ case SLJIT_SIG_GREATER_EQUAL:+ case SLJIT_SIG_LESS_EQUAL:+ case SLJIT_NOT_OVERFLOW:+ case SLJIT_MUL_NOT_OVERFLOW:+ ins = MOVZ | TA(OTHER_FLAG);+ break;+ case SLJIT_EQUAL_F64:+ case SLJIT_LESS_F64:+ case SLJIT_LESS_EQUAL_F64:+ case SLJIT_UNORDERED_F64:+ ins = MOVT;+ break;+ case SLJIT_NOT_EQUAL_F64:+ case SLJIT_GREATER_EQUAL_F64:+ case SLJIT_GREATER_F64:+ case SLJIT_ORDERED_F64:+ ins = MOVF;+ break;+ default:+ ins = MOVZ | TA(OTHER_FLAG);+ SLJIT_UNREACHABLE();+ break;+ }++ return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg));++#else /* SLJIT_MIPS_REV < 1 */+ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);+#endif /* SLJIT_MIPS_REV >= 1 */+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_put_label *put_label;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));+ PTR_FAIL_IF(!put_label);+ set_put_label(put_label, compiler, 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ PTR_FAIL_IF(emit_const(compiler, dst_r, 0));+#else+ PTR_FAIL_IF(push_inst(compiler, dst_r, UNMOVABLE_INS));+ compiler->size += 5;+#endif++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));++ return put_label;+}
+ src/c/pcre2/src/sljit/sljitNativePPC_32.c view
@@ -0,0 +1,275 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/* ppc 32-bit arch dependent functions. */++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)+{+ if (imm <= SIMM_MAX && imm >= SIMM_MIN)+ return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));++ if (!(imm & ~0xffff))+ return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));++ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));+ return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;+}++#define INS_CLEAR_LEFT(dst, src, from) \+ (RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1))++static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,+ sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)+{+ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if (dst != src2)+ return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S8)+ return push_inst(compiler, EXTSB | S(src2) | A(dst));+ return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));+ }+ else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)+ return push_inst(compiler, EXTSB | S(src2) | A(dst));+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S16)+ return push_inst(compiler, EXTSH | S(src2) | A(dst));+ return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));+ }+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_NOT:+ SLJIT_ASSERT(src1 == TMP_REG1);+ return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));++ case SLJIT_NEG:+ SLJIT_ASSERT(src1 == TMP_REG1);+ /* Setting XER SO is not enough, CR SO is also needed. */+ return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));++ case SLJIT_CLZ:+ SLJIT_ASSERT(src1 == TMP_REG1);+ return push_inst(compiler, CNTLZW | S(src2) | A(dst));++ case SLJIT_ADD:+ if (flags & ALT_FORM1) {+ /* Setting XER SO is not enough, CR SO is also needed. */+ return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));+ }++ if (flags & ALT_FORM2) {+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */+ SLJIT_ASSERT(src2 == TMP_REG2);++ if (flags & ALT_FORM3)+ return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);++ if (flags & ALT_FORM4) {+ FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));+ src1 = dst;+ }++ return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);+ }+ if (!(flags & ALT_SET_FLAGS))+ return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));+ if (flags & ALT_FORM4)+ return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));+ return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));++ case SLJIT_ADDC:+ return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));++ case SLJIT_SUB:+ if (flags & ALT_FORM1) {+ if (flags & ALT_FORM2) {+ FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));+ if (!(flags & ALT_FORM3))+ return SLJIT_SUCCESS;+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));+ }+ FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));+ if (!(flags & ALT_FORM3))+ return SLJIT_SUCCESS;+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));+ }++ if (flags & ALT_FORM2) {+ /* Setting XER SO is not enough, CR SO is also needed. */+ return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));+ }++ if (flags & ALT_FORM3) {+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);+ }++ if (flags & ALT_FORM4) {+ if (flags & ALT_FORM5) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm);+ }+ return push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2));+ }++ if (!(flags & ALT_SET_FLAGS))+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));+ if (flags & ALT_FORM5)+ return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));+ return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));++ case SLJIT_SUBC:+ return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));++ case SLJIT_MUL:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);+ }+ return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));++ case SLJIT_AND:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);+ }+ return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_OR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));+ return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));+ }+ return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_XOR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));+ return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));+ }+ return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_SHL:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ compiler->imm &= 0x1f;+ return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));+ }+ return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_LSHR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ compiler->imm &= 0x1f;+ return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));+ }+ return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_ASHR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ compiler->imm &= 0x1f;+ return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));+ }+ return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)+{+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));+ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ sljit_ins *inst = (sljit_ins *)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);+ inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);+ inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, new_constant, executable_offset);+}
+ src/c/pcre2/src/sljit/sljitNativePPC_64.c view
@@ -0,0 +1,495 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/* ppc 64-bit arch dependent functions. */++#if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)+#define ASM_SLJIT_CLZ(src, dst) \+ __asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )+#elif defined(__xlc__)+#error "Please enable GCC syntax for inline assembly statements"+#else+#error "Must implement count leading zeroes"+#endif++#define PUSH_RLDICR(reg, shift) \+ push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)+{+ sljit_uw tmp;+ sljit_uw shift;+ sljit_uw tmp2;+ sljit_uw shift2;++ if (imm <= SIMM_MAX && imm >= SIMM_MIN)+ return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));++ if (!(imm & ~0xffff))+ return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));++ if (imm <= 0x7fffffffl && imm >= -0x80000000l) {+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));+ return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;+ }++ /* Count leading zeroes. */+ tmp = (imm >= 0) ? imm : ~imm;+ ASM_SLJIT_CLZ(tmp, shift);+ SLJIT_ASSERT(shift > 0);+ shift--;+ tmp = (imm << shift);++ if ((tmp & ~0xffff000000000000ul) == 0) {+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));+ shift += 15;+ return PUSH_RLDICR(reg, shift);+ }++ if ((tmp & ~0xffffffff00000000ul) == 0) {+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(tmp >> 48)));+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32)));+ shift += 31;+ return PUSH_RLDICR(reg, shift);+ }++ /* Cut out the 16 bit from immediate. */+ shift += 15;+ tmp2 = imm & ((1ul << (63 - shift)) - 1);++ if (tmp2 <= 0xffff) {+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));+ FAIL_IF(PUSH_RLDICR(reg, shift));+ return push_inst(compiler, ORI | S(reg) | A(reg) | tmp2);+ }++ if (tmp2 <= 0xffffffff) {+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));+ FAIL_IF(PUSH_RLDICR(reg, shift));+ FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (tmp2 >> 16)));+ return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS;+ }++ ASM_SLJIT_CLZ(tmp2, shift2);+ tmp2 <<= shift2;++ if ((tmp2 & ~0xffff000000000000ul) == 0) {+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));+ shift2 += 15;+ shift += (63 - shift2);+ FAIL_IF(PUSH_RLDICR(reg, shift));+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (tmp2 >> 48)));+ return PUSH_RLDICR(reg, shift2);+ }++ /* The general version. */+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 48)));+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));+ FAIL_IF(PUSH_RLDICR(reg, 31));+ FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16)));+ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm));+}++/* Simplified mnemonics: clrldi. */+#define INS_CLEAR_LEFT(dst, src, from) \+ (RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5))++/* Sign extension for integer operations. */+#define UN_EXTS() \+ if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \+ FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \+ src2 = TMP_REG2; \+ }++#define BIN_EXTS() \+ if (flags & ALT_SIGN_EXT) { \+ if (flags & REG1_SOURCE) { \+ FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \+ src1 = TMP_REG1; \+ } \+ if (flags & REG2_SOURCE) { \+ FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \+ src2 = TMP_REG2; \+ } \+ }++#define BIN_IMM_EXTS() \+ if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \+ FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \+ src1 = TMP_REG1; \+ }++static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,+ sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)+{+ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if (dst != src2)+ return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S32)+ return push_inst(compiler, EXTSW | S(src2) | A(dst));+ return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));+ }+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S8)+ return push_inst(compiler, EXTSB | S(src2) | A(dst));+ return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));+ }+ else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)+ return push_inst(compiler, EXTSB | S(src2) | A(dst));+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S16)+ return push_inst(compiler, EXTSH | S(src2) | A(dst));+ return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));+ }+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_NOT:+ SLJIT_ASSERT(src1 == TMP_REG1);+ UN_EXTS();+ return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));++ case SLJIT_NEG:+ SLJIT_ASSERT(src1 == TMP_REG1);++ if ((flags & (ALT_FORM1 | ALT_SIGN_EXT)) == (ALT_FORM1 | ALT_SIGN_EXT)) {+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));+ FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(TMP_REG2)));+ return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));+ }++ UN_EXTS();+ /* Setting XER SO is not enough, CR SO is also needed. */+ return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));++ case SLJIT_CLZ:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if (flags & ALT_FORM1)+ return push_inst(compiler, CNTLZW | S(src2) | A(dst));+ return push_inst(compiler, CNTLZD | S(src2) | A(dst));++ case SLJIT_ADD:+ if (flags & ALT_FORM1) {+ if (flags & ALT_SIGN_EXT) {+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));+ src1 = TMP_REG1;+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));+ src2 = TMP_REG2;+ }+ /* Setting XER SO is not enough, CR SO is also needed. */+ FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)));+ if (flags & ALT_SIGN_EXT)+ return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));+ return SLJIT_SUCCESS;+ }++ if (flags & ALT_FORM2) {+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */+ SLJIT_ASSERT(src2 == TMP_REG2);++ if (flags & ALT_FORM3)+ return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);++ if (flags & ALT_FORM4) {+ FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));+ src1 = dst;+ }++ return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ BIN_IMM_EXTS();+ return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);+ }+ if (!(flags & ALT_SET_FLAGS))+ return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));+ BIN_EXTS();+ if (flags & ALT_FORM4)+ return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));+ return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));++ case SLJIT_ADDC:+ BIN_EXTS();+ return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));++ case SLJIT_SUB:+ if (flags & ALT_FORM1) {+ if (flags & ALT_FORM2) {+ FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));+ if (!(flags & ALT_FORM3))+ return SLJIT_SUCCESS;+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));+ }+ FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));+ if (!(flags & ALT_FORM3))+ return SLJIT_SUCCESS;+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));+ }++ if (flags & ALT_FORM2) {+ if (flags & ALT_SIGN_EXT) {+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));+ src1 = TMP_REG1;+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));+ src2 = TMP_REG2;+ }+ /* Setting XER SO is not enough, CR SO is also needed. */+ FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));+ if (flags & ALT_SIGN_EXT)+ return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));+ return SLJIT_SUCCESS;+ }++ if (flags & ALT_FORM3) {+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);+ }++ if (flags & ALT_FORM4) {+ if (flags & ALT_FORM5) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);+ }+ return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));+ }++ if (!(flags & ALT_SET_FLAGS))+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));+ BIN_EXTS();+ if (flags & ALT_FORM5)+ return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));+ return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));++ case SLJIT_SUBC:+ BIN_EXTS();+ return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));++ case SLJIT_MUL:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);+ }+ BIN_EXTS();+ if (flags & ALT_FORM2)+ return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));+ return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));++ case SLJIT_AND:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);+ }+ return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_OR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));+ return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));+ }+ return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_XOR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));+ return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));+ }+ return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_SHL:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ if (flags & ALT_FORM2) {+ compiler->imm &= 0x1f;+ return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));+ }+ compiler->imm &= 0x3f;+ return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));+ }+ return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_LSHR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ if (flags & ALT_FORM2) {+ compiler->imm &= 0x1f;+ return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));+ }+ compiler->imm &= 0x3f;+ return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));+ }+ return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_ASHR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ if (flags & ALT_FORM2) {+ compiler->imm &= 0x1f;+ return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));+ }+ compiler->imm &= 0x3f;+ return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4));+ }+ return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2));+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)+{+ sljit_s32 arg_count = 0;+ sljit_s32 word_arg_count = 0;+ sljit_s32 types = 0;+ sljit_s32 reg = 0;++ if (src)+ reg = *src & REG_MASK;++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);++ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ case SLJIT_ARG_TYPE_F64:+ arg_count++;+ break;+ default:+ arg_count++;+ word_arg_count++;++ if (arg_count != word_arg_count && arg_count == reg) {+ FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg)));+ *src = TMP_CALL_REG;+ }+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ while (types) {+ switch (types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ case SLJIT_ARG_TYPE_F64:+ arg_count--;+ break;+ default:+ if (arg_count != word_arg_count)+ FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count)));++ arg_count--;+ word_arg_count--;+ break;+ }++ types >>= SLJIT_DEF_SHIFT;+ }++ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)+{+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));+ FAIL_IF(PUSH_RLDICR(reg, 31));+ FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16)));+ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ sljit_ins *inst = (sljit_ins*)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);+ inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);+ inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);+ inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);+ inst[4] = (inst[4] & 0xffff0000) | (new_target & 0xffff);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 5);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, new_constant, executable_offset);+}
+ src/c/pcre2/src/sljit/sljitNativePPC_common.c view
@@ -0,0 +1,2408 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+ return "PowerPC" SLJIT_CPUINFO;+}++/* Length of an instruction word.+ Both for ppc-32 and ppc-64. */+typedef sljit_u32 sljit_ins;++#if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \+ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define SLJIT_PPC_STACK_FRAME_V2 1+#endif++#ifdef _AIX+#include <sys/cache.h>+#endif++#if (defined _CALL_ELF && _CALL_ELF == 2)+#define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1+#endif++#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)++static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)+{+#ifdef _AIX+ _sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from));+#elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)+# if defined(_ARCH_PWR) || defined(_ARCH_PWR2)+ /* Cache flush for POWER architecture. */+ while (from < to) {+ __asm__ volatile (+ "clf 0, %0\n"+ "dcs\n"+ : : "r"(from)+ );+ from++;+ }+ __asm__ volatile ( "ics" );+# elif defined(_ARCH_COM) && !defined(_ARCH_PPC)+# error "Cache flush is not implemented for PowerPC/POWER common mode."+# else+ /* Cache flush for PowerPC architecture. */+ while (from < to) {+ __asm__ volatile (+ "dcbf 0, %0\n"+ "sync\n"+ "icbi 0, %0\n"+ : : "r"(from)+ );+ from++;+ }+ __asm__ volatile ( "isync" );+# endif+# ifdef __xlc__+# warning "This file may fail to compile if -qfuncsect is used"+# endif+#elif defined(__xlc__)+#error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"+#else+#error "This platform requires a cache flush implementation."+#endif /* _AIX */+}++#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */++#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)+#define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4)++#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)+#define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 5)+#else+#define TMP_CALL_REG TMP_REG2+#endif++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {+ 0, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 9, 10, 31, 12+};++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {+ 0, 1, 2, 3, 4, 5, 6, 0, 7+};++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */+#define D(d) (reg_map[d] << 21)+#define S(s) (reg_map[s] << 21)+#define A(a) (reg_map[a] << 16)+#define B(b) (reg_map[b] << 11)+#define C(c) (reg_map[c] << 6)+#define FD(fd) (freg_map[fd] << 21)+#define FS(fs) (freg_map[fs] << 21)+#define FA(fa) (freg_map[fa] << 16)+#define FB(fb) (freg_map[fb] << 11)+#define FC(fc) (freg_map[fc] << 6)+#define IMM(imm) ((imm) & 0xffff)+#define CRD(d) ((d) << 21)++/* Instruction bit sections.+ OE and Rc flag (see ALT_SET_FLAGS). */+#define OE(flags) ((flags) & ALT_SET_FLAGS)+/* Rc flag (see ALT_SET_FLAGS). */+#define RC(flags) (((flags) & ALT_SET_FLAGS) >> 10)+#define HI(opcode) ((opcode) << 26)+#define LO(opcode) ((opcode) << 1)++#define ADD (HI(31) | LO(266))+#define ADDC (HI(31) | LO(10))+#define ADDE (HI(31) | LO(138))+#define ADDI (HI(14))+#define ADDIC (HI(13))+#define ADDIS (HI(15))+#define ADDME (HI(31) | LO(234))+#define AND (HI(31) | LO(28))+#define ANDI (HI(28))+#define ANDIS (HI(29))+#define Bx (HI(18))+#define BCx (HI(16))+#define BCCTR (HI(19) | LO(528) | (3 << 11))+#define BLR (HI(19) | LO(16) | (0x14 << 21))+#define CNTLZD (HI(31) | LO(58))+#define CNTLZW (HI(31) | LO(26))+#define CMP (HI(31) | LO(0))+#define CMPI (HI(11))+#define CMPL (HI(31) | LO(32))+#define CMPLI (HI(10))+#define CROR (HI(19) | LO(449))+#define DCBT (HI(31) | LO(278))+#define DIVD (HI(31) | LO(489))+#define DIVDU (HI(31) | LO(457))+#define DIVW (HI(31) | LO(491))+#define DIVWU (HI(31) | LO(459))+#define EXTSB (HI(31) | LO(954))+#define EXTSH (HI(31) | LO(922))+#define EXTSW (HI(31) | LO(986))+#define FABS (HI(63) | LO(264))+#define FADD (HI(63) | LO(21))+#define FADDS (HI(59) | LO(21))+#define FCFID (HI(63) | LO(846))+#define FCMPU (HI(63) | LO(0))+#define FCTIDZ (HI(63) | LO(815))+#define FCTIWZ (HI(63) | LO(15))+#define FDIV (HI(63) | LO(18))+#define FDIVS (HI(59) | LO(18))+#define FMR (HI(63) | LO(72))+#define FMUL (HI(63) | LO(25))+#define FMULS (HI(59) | LO(25))+#define FNEG (HI(63) | LO(40))+#define FRSP (HI(63) | LO(12))+#define FSUB (HI(63) | LO(20))+#define FSUBS (HI(59) | LO(20))+#define LD (HI(58) | 0)+#define LWZ (HI(32))+#define MFCR (HI(31) | LO(19))+#define MFLR (HI(31) | LO(339) | 0x80000)+#define MFXER (HI(31) | LO(339) | 0x10000)+#define MTCTR (HI(31) | LO(467) | 0x90000)+#define MTLR (HI(31) | LO(467) | 0x80000)+#define MTXER (HI(31) | LO(467) | 0x10000)+#define MULHD (HI(31) | LO(73))+#define MULHDU (HI(31) | LO(9))+#define MULHW (HI(31) | LO(75))+#define MULHWU (HI(31) | LO(11))+#define MULLD (HI(31) | LO(233))+#define MULLI (HI(7))+#define MULLW (HI(31) | LO(235))+#define NEG (HI(31) | LO(104))+#define NOP (HI(24))+#define NOR (HI(31) | LO(124))+#define OR (HI(31) | LO(444))+#define ORI (HI(24))+#define ORIS (HI(25))+#define RLDICL (HI(30))+#define RLWINM (HI(21))+#define SLD (HI(31) | LO(27))+#define SLW (HI(31) | LO(24))+#define SRAD (HI(31) | LO(794))+#define SRADI (HI(31) | LO(413 << 1))+#define SRAW (HI(31) | LO(792))+#define SRAWI (HI(31) | LO(824))+#define SRD (HI(31) | LO(539))+#define SRW (HI(31) | LO(536))+#define STD (HI(62) | 0)+#define STDU (HI(62) | 1)+#define STDUX (HI(31) | LO(181))+#define STFIWX (HI(31) | LO(983))+#define STW (HI(36))+#define STWU (HI(37))+#define STWUX (HI(31) | LO(183))+#define SUBF (HI(31) | LO(40))+#define SUBFC (HI(31) | LO(8))+#define SUBFE (HI(31) | LO(136))+#define SUBFIC (HI(8))+#define XOR (HI(31) | LO(316))+#define XORI (HI(26))+#define XORIS (HI(27))++#define SIMM_MAX (0x7fff)+#define SIMM_MIN (-0x8000)+#define UIMM_MAX (0xffff)++#define RLDI(dst, src, sh, mb, type) \+ (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))++#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)+{+ sljit_sw* ptrs;+ if (func_ptr)+ *func_ptr = (void*)context;+ ptrs = (sljit_sw*)func;+ context->addr = addr ? addr : ptrs[0];+ context->r2 = ptrs[1];+ context->r11 = ptrs[2];+}+#endif++static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)+{+ sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ *ptr = ins;+ compiler->size++;+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_sw diff;+ sljit_uw target_addr;+ sljit_sw extra_jump_flags;++#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))+ return 0;+#else+ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ return 0;+#endif++ if (jump->flags & JUMP_ADDR)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;+ }++#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (jump->flags & IS_CALL)+ goto keep_address;+#endif++ diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l;++ extra_jump_flags = 0;+ if (jump->flags & IS_COND) {+ if (diff <= 0x7fff && diff >= -0x8000) {+ jump->flags |= PATCH_B;+ return 1;+ }+ if (target_addr <= 0xffff) {+ jump->flags |= PATCH_B | PATCH_ABS_B;+ return 1;+ }+ extra_jump_flags = REMOVE_COND;++ diff -= sizeof(sljit_ins);+ }++ if (diff <= 0x01ffffff && diff >= -0x02000000) {+ jump->flags |= PATCH_B | extra_jump_flags;+ return 1;+ }++ if (target_addr <= 0x03ffffff) {+ jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags;+ return 1;+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)+keep_address:+#endif+ if (target_addr <= 0x7fffffff) {+ jump->flags |= PATCH_ABS32;+ return 1;+ }++ if (target_addr <= 0x7fffffffffffl) {+ jump->flags |= PATCH_ABS48;+ return 1;+ }+#endif++ return 0;+}++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)++static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)+{+ if (max_label < 0x100000000l) {+ put_label->flags = 0;+ return 1;+ }++ if (max_label < 0x1000000000000l) {+ put_label->flags = 1;+ return 3;+ }++ put_label->flags = 2;+ return 4;+}++static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)+{+ sljit_uw addr = put_label->label->addr;+ sljit_ins *inst = (sljit_ins *)put_label->addr;+ sljit_s32 reg = *inst;++ if (put_label->flags == 0) {+ SLJIT_ASSERT(addr < 0x100000000l);+ inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 16);+ }+ else {+ if (put_label->flags == 1) {+ SLJIT_ASSERT(addr < 0x1000000000000l);+ inst[0] = ORI | S(TMP_ZERO) | A(reg) | IMM(addr >> 32);+ }+ else {+ inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 48);+ inst[1] = ORI | S(reg) | A(reg) | IMM((addr >> 32) & 0xffff);+ inst ++;+ }++ inst[1] = RLDI(reg, reg, 32, 31, 1);+ inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff);+ inst += 2;+ }++ inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff);+}++#endif++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ sljit_uw next_addr;+ sljit_sw executable_offset;+ sljit_uw addr;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ struct sljit_put_label *put_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));+ reverse_buf(compiler);++#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));+#else+ compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));+#endif+#endif+ code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);+ PTR_FAIL_WITH_EXEC_IF(code);+ buf = compiler->buf;++ code_ptr = code;+ word_count = 0;+ next_addr = 0;+ executable_offset = SLJIT_EXEC_OFFSET(code);++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ put_label = compiler->put_labels;++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+ *code_ptr = *buf_ptr++;+ if (next_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);++ /* These structures are ordered by their address. */+ if (label && label->size == word_count) {+ /* Just recording the address. */+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = code_ptr - code;+ label = label->next;+ }+ if (jump && jump->addr == word_count) {+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ jump->addr = (sljit_uw)(code_ptr - 3);+#else+ jump->addr = (sljit_uw)(code_ptr - 6);+#endif+ if (detect_jump_type(jump, code_ptr, code, executable_offset)) {+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ code_ptr[-3] = code_ptr[0];+ code_ptr -= 3;+#else+ if (jump->flags & PATCH_ABS32) {+ code_ptr -= 3;+ code_ptr[-1] = code_ptr[2];+ code_ptr[0] = code_ptr[3];+ }+ else if (jump->flags & PATCH_ABS48) {+ code_ptr--;+ code_ptr[-1] = code_ptr[0];+ code_ptr[0] = code_ptr[1];+ /* rldicr rX,rX,32,31 -> rX,rX,16,47 */+ SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);+ code_ptr[-3] ^= 0x8422;+ /* oris -> ori */+ code_ptr[-2] ^= 0x4000000;+ }+ else {+ code_ptr[-6] = code_ptr[0];+ code_ptr -= 6;+ }+#endif+ if (jump->flags & REMOVE_COND) {+ code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);+ code_ptr++;+ jump->addr += sizeof(sljit_ins);+ code_ptr[0] = Bx;+ jump->flags -= IS_COND;+ }+ }+ jump = jump->next;+ }+ if (const_ && const_->addr == word_count) {+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ }+ if (put_label && put_label->addr == word_count) {+ SLJIT_ASSERT(put_label->label);+ put_label->addr = (sljit_uw)code_ptr;+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));+ word_count += 4;+#endif+ put_label = put_label->next;+ }+ next_addr = compute_next_addr(label, jump, const_, put_label);+ }+ code_ptr ++;+ word_count ++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = code_ptr - code;+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(!put_label);++#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)));+#else+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);+#endif++ jump = compiler->jumps;+ while (jump) {+ do {+ addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;+ buf_ptr = (sljit_ins *)jump->addr;++ if (jump->flags & PATCH_B) {+ if (jump->flags & IS_COND) {+ if (!(jump->flags & PATCH_ABS_B)) {+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);+ SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);+ *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);+ }+ else {+ SLJIT_ASSERT(addr <= 0xffff);+ *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);+ }+ }+ else {+ if (!(jump->flags & PATCH_ABS_B)) {+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);+ SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);+ *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);+ }+ else {+ SLJIT_ASSERT(addr <= 0x03ffffff);+ *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);+ }+ }+ break;+ }++ /* Set the fields of immediate loads. */+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);+#else+ if (jump->flags & PATCH_ABS32) {+ SLJIT_ASSERT(addr <= 0x7fffffff);+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);+ break;+ }+ if (jump->flags & PATCH_ABS48) {+ SLJIT_ASSERT(addr <= 0x7fffffffffff);+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);+ buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);+ break;+ }+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);+ buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);+ buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);+ buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff);+#endif+ } while (0);+ jump = jump->next;+ }++ put_label = compiler->put_labels;+ while (put_label) {+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ addr = put_label->label->addr;+ buf_ptr = (sljit_ins *)put_label->addr;++ SLJIT_ASSERT((buf_ptr[0] & 0xfc1f0000) == ADDIS && (buf_ptr[1] & 0xfc000000) == ORI);+ buf_ptr[0] |= (addr >> 16) & 0xffff;+ buf_ptr[1] |= addr & 0xffff;+#else+ put_label_set(put_label);+#endif+ put_label = put_label->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);++ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);++#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (((sljit_sw)code_ptr) & 0x4)+ code_ptr++;+#endif+ sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);+#endif++ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ SLJIT_CACHE_FLUSH(code, code_ptr);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);++#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+ return code_ptr;+#else+ return code;+#endif+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ switch (feature_type) {+ case SLJIT_HAS_FPU:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return SLJIT_IS_FPU_AVAILABLE;+#else+ /* Available by default. */+ return 1;+#endif++ /* A saved register is set to a zero value. */+ case SLJIT_HAS_ZERO_REGISTER:+ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_PREFETCH:+ return 1;++ default:+ return 0;+ }+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++/* inp_flags: */++/* Creates an index in data_transfer_insts array. */+#define LOAD_DATA 0x01+#define INDEXED 0x02+#define SIGNED_DATA 0x04++#define WORD_DATA 0x00+#define BYTE_DATA 0x08+#define HALF_DATA 0x10+#define INT_DATA 0x18+/* Separates integer and floating point registers */+#define GPR_REG 0x1f+#define DOUBLE_DATA 0x20++#define MEM_MASK 0x7f++/* Other inp_flags. */++/* Integer opertion and set flags -> requires exts on 64 bit systems. */+#define ALT_SIGN_EXT 0x000100+/* This flag affects the RC() and OERC() macros. */+#define ALT_SET_FLAGS 0x000400+#define ALT_FORM1 0x001000+#define ALT_FORM2 0x002000+#define ALT_FORM3 0x004000+#define ALT_FORM4 0x008000+#define ALT_FORM5 0x010000++/* Source and destination is register. */+#define REG_DEST 0x000001+#define REG1_SOURCE 0x000002+#define REG2_SOURCE 0x000004+/*+ALT_SIGN_EXT 0x000100+ALT_SET_FLAGS 0x000200+ALT_FORM1 0x001000+...+ALT_FORM5 0x010000 */++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+#include "sljitNativePPC_32.c"+#else+#include "sljitNativePPC_64.c"+#endif++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+#define STACK_STORE STW+#define STACK_LOAD LWZ+#else+#define STACK_STORE STD+#define STACK_LOAD LD+#endif++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 args, i, tmp, offs;++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ FAIL_IF(push_inst(compiler, MFLR | D(0)));+ offs = -(sljit_s32)(sizeof(sljit_sw));+ FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));++ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = SLJIT_S0; i >= tmp; i--) {+ offs -= (sljit_s32)(sizeof(sljit_sw));+ FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ offs -= (sljit_s32)(sizeof(sljit_sw));+ FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));+ }++ SLJIT_ASSERT(offs == -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1));++#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)+ FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));+#else+ FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));+#endif++ FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));++ args = get_arg_count(arg_types);++ if (args >= 1)+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(SLJIT_S0) | B(SLJIT_R0)));+ if (args >= 2)+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R1) | A(SLJIT_S1) | B(SLJIT_R1)));+ if (args >= 3)+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R2) | A(SLJIT_S2) | B(SLJIT_R2)));++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;+ local_size = (local_size + 15) & ~0xf;+ compiler->local_size = local_size;++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ if (local_size <= SIMM_MAX)+ FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));+ else {+ FAIL_IF(load_immediate(compiler, 0, -local_size));+ FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));+ }+#else+ if (local_size <= SIMM_MAX)+ FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));+ else {+ FAIL_IF(load_immediate(compiler, 0, -local_size));+ FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));+ }+#endif++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;+ compiler->local_size = (local_size + 15) & ~0xf;+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 i, tmp, offs;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));++ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));++ if (compiler->local_size <= SIMM_MAX)+ FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_SP) | A(SLJIT_SP) | IMM(compiler->local_size)));+ else {+ FAIL_IF(load_immediate(compiler, 0, compiler->local_size));+ FAIL_IF(push_inst(compiler, ADD | D(SLJIT_SP) | A(SLJIT_SP) | B(0)));+ }++#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));+#else+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));+#endif++ offs = -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);++ tmp = compiler->scratches;+ for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));+ offs += (sljit_s32)(sizeof(sljit_sw));+ }++ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = tmp; i <= SLJIT_S0; i++) {+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));+ offs += (sljit_s32)(sizeof(sljit_sw));+ }++ FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));+ SLJIT_ASSERT(offs == -(sljit_sw)(sizeof(sljit_sw)));++ FAIL_IF(push_inst(compiler, MTLR | S(0)));+ FAIL_IF(push_inst(compiler, BLR));++ return SLJIT_SUCCESS;+}++#undef STACK_STORE+#undef STACK_LOAD++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++/* s/l - store/load (1 bit)+ i/x - immediate/indexed form+ u/s - signed/unsigned (1 bit)+ w/b/h/i - word/byte/half/int allowed (2 bit)++ Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */++/* 64 bit only: [reg+imm] must be aligned to 4 bytes. */+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define INT_ALIGNED 0x10000+#endif++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+#define ARCH_32_64(a, b) a+#define INST_CODE_AND_DST(inst, flags, reg) \+ ((inst) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))+#else+#define ARCH_32_64(a, b) b+#define INST_CODE_AND_DST(inst, flags, reg) \+ (((inst) & ~INT_ALIGNED) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))+#endif++static const sljit_ins data_transfer_insts[64 + 16] = {++/* -------- Integer -------- */++/* Word. */++/* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),+/* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),+/* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),+/* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),++/* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),+/* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),+/* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),+/* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),++/* Byte. */++/* b u i s */ HI(38) /* stb */,+/* b u i l */ HI(34) /* lbz */,+/* b u x s */ HI(31) | LO(215) /* stbx */,+/* b u x l */ HI(31) | LO(87) /* lbzx */,++/* b s i s */ HI(38) /* stb */,+/* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,+/* b s x s */ HI(31) | LO(215) /* stbx */,+/* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,++/* Half. */++/* h u i s */ HI(44) /* sth */,+/* h u i l */ HI(40) /* lhz */,+/* h u x s */ HI(31) | LO(407) /* sthx */,+/* h u x l */ HI(31) | LO(279) /* lhzx */,++/* h s i s */ HI(44) /* sth */,+/* h s i l */ HI(42) /* lha */,+/* h s x s */ HI(31) | LO(407) /* sthx */,+/* h s x l */ HI(31) | LO(343) /* lhax */,++/* Int. */++/* i u i s */ HI(36) /* stw */,+/* i u i l */ HI(32) /* lwz */,+/* i u x s */ HI(31) | LO(151) /* stwx */,+/* i u x l */ HI(31) | LO(23) /* lwzx */,++/* i s i s */ HI(36) /* stw */,+/* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),+/* i s x s */ HI(31) | LO(151) /* stwx */,+/* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),++/* -------- Floating point -------- */++/* d i s */ HI(54) /* stfd */,+/* d i l */ HI(50) /* lfd */,+/* d x s */ HI(31) | LO(727) /* stfdx */,+/* d x l */ HI(31) | LO(599) /* lfdx */,++/* s i s */ HI(52) /* stfs */,+/* s i l */ HI(48) /* lfs */,+/* s x s */ HI(31) | LO(663) /* stfsx */,+/* s x l */ HI(31) | LO(535) /* lfsx */,+};++static const sljit_ins updated_data_transfer_insts[64] = {++/* -------- Integer -------- */++/* Word. */++/* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),+/* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),+/* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),+/* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),++/* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),+/* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),+/* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),+/* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),++/* Byte. */++/* b u i s */ HI(39) /* stbu */,+/* b u i l */ HI(35) /* lbzu */,+/* b u x s */ HI(31) | LO(247) /* stbux */,+/* b u x l */ HI(31) | LO(119) /* lbzux */,++/* b s i s */ HI(39) /* stbu */,+/* b s i l */ 0 /* no such instruction */,+/* b s x s */ HI(31) | LO(247) /* stbux */,+/* b s x l */ 0 /* no such instruction */,++/* Half. */++/* h u i s */ HI(45) /* sthu */,+/* h u i l */ HI(41) /* lhzu */,+/* h u x s */ HI(31) | LO(439) /* sthux */,+/* h u x l */ HI(31) | LO(311) /* lhzux */,++/* h s i s */ HI(45) /* sthu */,+/* h s i l */ HI(43) /* lhau */,+/* h s x s */ HI(31) | LO(439) /* sthux */,+/* h s x l */ HI(31) | LO(375) /* lhaux */,++/* Int. */++/* i u i s */ HI(37) /* stwu */,+/* i u i l */ HI(33) /* lwzu */,+/* i u x s */ HI(31) | LO(183) /* stwux */,+/* i u x l */ HI(31) | LO(55) /* lwzux */,++/* i s i s */ HI(37) /* stwu */,+/* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),+/* i s x s */ HI(31) | LO(183) /* stwux */,+/* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),++/* -------- Floating point -------- */++/* d i s */ HI(55) /* stfdu */,+/* d i l */ HI(51) /* lfdu */,+/* d x s */ HI(31) | LO(759) /* stfdux */,+/* d x l */ HI(31) | LO(631) /* lfdux */,++/* s i s */ HI(53) /* stfsu */,+/* s i l */ HI(49) /* lfsu */,+/* s x s */ HI(31) | LO(695) /* stfsux */,+/* s x l */ HI(31) | LO(567) /* lfsux */,+};++#undef ARCH_32_64++/* Simple cases, (no caching is required). */+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)+{+ sljit_ins inst;+ sljit_s32 offs_reg;+ sljit_sw high_short;++ /* Should work when (arg & REG_MASK) == 0. */+ SLJIT_ASSERT(A(0) == 0);+ SLJIT_ASSERT(arg & SLJIT_MEM);++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;+ offs_reg = OFFS_REG(arg);++ if (argw != 0) {+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | (argw << 11) | ((31 - argw) << 1)));+#else+ FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1)));+#endif+ offs_reg = tmp_reg;+ }++ inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ SLJIT_ASSERT(!(inst & INT_ALIGNED));+#endif++ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));+ }++ inst = data_transfer_insts[inp_flags & MEM_MASK];+ arg &= REG_MASK;++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {+ FAIL_IF(load_immediate(compiler, tmp_reg, argw));++ inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));+ }+#endif++ if (argw <= SIMM_MAX && argw >= SIMM_MIN)+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {+#endif++ high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff;++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l);+#else+ SLJIT_ASSERT(high_short);+#endif++ FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM(high_short >> 16)));+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ }++ /* The rest is PPC-64 only. */++ FAIL_IF(load_immediate(compiler, tmp_reg, argw));++ inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));+#endif+}++static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ /* arg1 goes to TMP_REG1 or src reg+ arg2 goes to TMP_REG2, imm or src reg+ result goes to TMP_REG2, so put result can use TMP_REG1. */+ sljit_s32 dst_r = TMP_REG2;+ sljit_s32 src1_r;+ sljit_s32 src2_r;+ sljit_s32 sugg_src2_r = TMP_REG2;+ sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);++ /* Destination check. */+ if (SLOW_IS_REG(dst)) {+ dst_r = dst;+ flags |= REG_DEST;++ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)+ sugg_src2_r = dst_r;+ }++ /* Source 1. */+ if (FAST_IS_REG(src1)) {+ src1_r = src1;+ flags |= REG1_SOURCE;+ }+ else if (src1 & SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));+ src1_r = TMP_REG1;+ }+ else {+ FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));+ src1_r = TMP_REG1;+ }++ /* Source 2. */+ if (FAST_IS_REG(src2)) {+ src2_r = src2;+ flags |= REG2_SOURCE;++ if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)+ dst_r = src2_r;+ }+ else if (src2 & SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));+ src2_r = sugg_src2_r;+ }+ else {+ FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, TMP_REG2));+ src2_r = sugg_src2_r;+ }++ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;++ return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ sljit_s32 int_op = op & SLJIT_I32_OP;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ case SLJIT_NOP:+ return push_inst(compiler, NOP);+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));+ return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));+#else+ FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));+ return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));+#endif+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIVMOD_SW:+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) : (op == SLJIT_DIVMOD_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));+ FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));+#else+ FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));+ FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));+#endif+ return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));+ case SLJIT_DIV_UW:+ case SLJIT_DIV_SW:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ return push_inst(compiler, (int_op ? (op == SLJIT_DIV_UW ? DIVWU : DIVW) : (op == SLJIT_DIV_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));+#else+ return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));+#endif+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw)+{+ if (!(src & OFFS_REG_MASK)) {+ if (srcw == 0 && (src & REG_MASK) != SLJIT_UNUSED)+ return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));++ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ /* Works with SLJIT_MEM0() case as well. */+ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));+ }++ srcw &= 0x3;++ if (srcw == 0)+ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));++#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | (srcw << 11) | ((31 - srcw) << 1)));+#else+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1)));+#endif+ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));+}++#define EMIT_MOV(type, type_flags, type_cast) \+ emit_op(compiler, (src & SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? type_cast srcw : srcw)++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;+ sljit_s32 op_flags = GET_ALL_FLAGS(op);++ CHECK_ERROR();+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++ op = GET_OPCODE(op);+ if ((src & SLJIT_IMM) && srcw == 0)+ src = TMP_ZERO;++ if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));++ if (op < SLJIT_NOT && FAST_IS_REG(src) && src == dst) {+ if (!TYPE_CAST_NEEDED(op))+ return SLJIT_SUCCESS;+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (op_flags & SLJIT_I32_OP) {+ if (op < SLJIT_NOT) {+ if (src & SLJIT_MEM) {+ if (op == SLJIT_MOV_S32)+ op = SLJIT_MOV_U32;+ }+ else if (src & SLJIT_IMM) {+ if (op == SLJIT_MOV_U32)+ op = SLJIT_MOV_S32;+ }+ }+ else {+ /* Most operations expect sign extended arguments. */+ flags |= INT_DATA | SIGNED_DATA;+ if (HAS_FLAGS(op_flags))+ flags |= ALT_SIGN_EXT;+ }+ }+#endif++ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+#endif+ return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ case SLJIT_MOV_U32:+ return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));++ case SLJIT_MOV_S32:+ return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));+#endif++ case SLJIT_MOV_U8:+ return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));++ case SLJIT_MOV_S8:+ return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));++ case SLJIT_MOV_U16:+ return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));++ case SLJIT_MOV_S16:+ return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));++ case SLJIT_NOT:+ return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_NEG:+ return emit_op(compiler, SLJIT_NEG, flags | (GET_FLAG_TYPE(op_flags) ? ALT_FORM1 : 0), dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_CLZ:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_I32_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);+#else+ return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw);+#endif+ }++ return SLJIT_SUCCESS;+}++#undef EMIT_MOV++#define TEST_SL_IMM(src, srcw) \+ (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)++#define TEST_UL_IMM(src, srcw) \+ (((src) & SLJIT_IMM) && !((srcw) & ~0xffff))++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define TEST_SH_IMM(src, srcw) \+ (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)+#else+#define TEST_SH_IMM(src, srcw) \+ (((src) & SLJIT_IMM) && !((srcw) & 0xffff))+#endif++#define TEST_UH_IMM(src, srcw) \+ (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000))++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define TEST_ADD_IMM(src, srcw) \+ (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)+#else+#define TEST_ADD_IMM(src, srcw) \+ ((src) & SLJIT_IMM)+#endif++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define TEST_UI_IMM(src, srcw) \+ (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff))+#else+#define TEST_UI_IMM(src, srcw) \+ ((src) & SLJIT_IMM)+#endif++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))+ return SLJIT_SUCCESS;++ if ((src1 & SLJIT_IMM) && src1w == 0)+ src1 = TMP_ZERO;+ if ((src2 & SLJIT_IMM) && src2w == 0)+ src2 = TMP_ZERO;++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (op & SLJIT_I32_OP) {+ /* Most operations expect sign extended arguments. */+ flags |= INT_DATA | SIGNED_DATA;+ if (src1 & SLJIT_IMM)+ src1w = (sljit_s32)(src1w);+ if (src2 & SLJIT_IMM)+ src2w = (sljit_s32)(src2w);+ if (HAS_FLAGS(op))+ flags |= ALT_SIGN_EXT;+ }+#endif+ if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);++ if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {+ if (TEST_SL_IMM(src2, src2w)) {+ compiler->imm = src2w & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_SL_IMM(src1, src1w)) {+ compiler->imm = src1w & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ if (TEST_SH_IMM(src2, src2w)) {+ compiler->imm = (src2w >> 16) & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_SH_IMM(src1, src1w)) {+ compiler->imm = (src1w >> 16) & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ /* Range between -1 and -32768 is covered above. */+ if (TEST_ADD_IMM(src2, src2w)) {+ compiler->imm = src2w & 0xffffffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_ADD_IMM(src1, src1w)) {+ compiler->imm = src1w & 0xffffffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ }+ if (HAS_FLAGS(op)) {+ if (TEST_SL_IMM(src2, src2w)) {+ compiler->imm = src2w & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_SL_IMM(src1, src1w)) {+ compiler->imm = src1w & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ }+ return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM4 : 0), dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_ADDC:+ return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SUB:+ if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {+ if (dst == SLJIT_UNUSED) {+ if (TEST_UL_IMM(src2, src2w)) {+ compiler->imm = src2w & 0xffff;+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);+ }++ if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {+ compiler->imm = src2w;+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);+ }++ if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);++ if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {+ if (TEST_SL_IMM(src2, -src2w)) {+ compiler->imm = (-src2w) & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_SL_IMM(src1, src1w)) {+ compiler->imm = src1w & 0xffff;+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ if (TEST_SH_IMM(src2, -src2w)) {+ compiler->imm = ((-src2w) >> 16) & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ /* Range between -1 and -32768 is covered above. */+ if (TEST_ADD_IMM(src2, -src2w)) {+ compiler->imm = -src2w & 0xffffffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ }++ if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) != GET_FLAG_TYPE(SLJIT_SET_CARRY)) {+ if (TEST_SL_IMM(src2, src2w)) {+ compiler->imm = src2w & 0xffff;+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);+ }++ if (TEST_SL_IMM(src2, -src2w)) {+ compiler->imm = (-src2w) & 0xffff;+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */+ return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SUBC:+ return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_MUL:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (op & SLJIT_I32_OP)+ flags |= ALT_FORM2;+#endif+ if (!HAS_FLAGS(op)) {+ if (TEST_SL_IMM(src2, src2w)) {+ compiler->imm = src2w & 0xffff;+ return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_SL_IMM(src1, src1w)) {+ compiler->imm = src1w & 0xffff;+ return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ }+ else+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));+ return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ /* Commutative unsigned operations. */+ if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {+ if (TEST_UL_IMM(src2, src2w)) {+ compiler->imm = src2w;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_UL_IMM(src1, src1w)) {+ compiler->imm = src1w;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ if (TEST_UH_IMM(src2, src2w)) {+ compiler->imm = (src2w >> 16) & 0xffff;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_UH_IMM(src1, src1w)) {+ compiler->imm = (src1w >> 16) & 0xffff;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ }+ if (GET_OPCODE(op) != SLJIT_AND && GET_OPCODE(op) != SLJIT_AND) {+ /* Unlike or and xor, and resets unwanted bits as well. */+ if (TEST_UI_IMM(src2, src2w)) {+ compiler->imm = src2w;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ if (TEST_UI_IMM(src1, src1w)) {+ compiler->imm = src1w;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);+ }+ }+ return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SHL:+ case SLJIT_LSHR:+ case SLJIT_ASHR:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (op & SLJIT_I32_OP)+ flags |= ALT_FORM2;+#endif+ if (src2 & SLJIT_IMM) {+ compiler->imm = src2w;+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);+ }+ return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, MTLR | S(src)));+ else {+ FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));+ FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));+ }++ return push_inst(compiler, BLR);+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ return emit_prefetch(compiler, src, srcw);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(reg));+ return reg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));+ return freg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_ins*)instruction);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6))+#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))+#else+#define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw))++#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw))+#define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw))+#else+#define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw))+#define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw))+#endif++#endif /* SLJIT_CONFIG_PPC_64 */++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ if (src & SLJIT_MEM) {+ /* We can ignore the temporary data store on the stack from caching point of view. */+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));+ src = TMP_FREG1;+ }++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ op = GET_OPCODE(op);+ FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));++ if (op == SLJIT_CONV_SW_FROM_F64) {+ if (FAST_IS_REG(dst)) {+ FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));+ return emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);+ }+ return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);+ }+#else+ FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));+#endif++ if (FAST_IS_REG(dst)) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET));+ FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));+ return emit_op_mem(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);+ }++ SLJIT_ASSERT(dst & SLJIT_MEM);++ if (dst & OFFS_REG_MASK) {+ dstw &= 0x3;+ if (dstw) {+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | (dstw << 11) | ((31 - dstw) << 1)));+#else+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1)));+#endif+ dstw = TMP_REG1;+ }+ else+ dstw = OFFS_REG(dst);+ }+ else {+ if ((dst & REG_MASK) && !dstw) {+ dstw = dst & REG_MASK;+ dst = 0;+ }+ else {+ /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */+ FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));+ dstw = TMP_REG1;+ }+ }++ return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)++ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_IMM) {+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)+ srcw = (sljit_s32)srcw;+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ }+ else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));+ else+ FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ if (FAST_IS_REG(src)) {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));+ FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));+ }+ else+ FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));++ FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);+ if (op & SLJIT_F32_OP)+ return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));+ return SLJIT_SUCCESS;++#else++ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;+ sljit_s32 invert_sign = 1;++ if (src & SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ 0x80000000));+ src = TMP_REG1;+ invert_sign = 0;+ }+ else if (!FAST_IS_REG(src)) {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));+ src = TMP_REG1;+ }++ /* First, a special double floating point value is constructed: (2^53 + (input xor (2^31)))+ The double precision format has exactly 53 bit precision, so the lower 32 bit represents+ the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000+ to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating+ point value, we need to substract 2^53 + 2^31 from the constructed value. */+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));+ if (invert_sign)+ FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));+ FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, TMP_REG1));+ FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));+ FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));+ FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));+ FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));++ FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);+ if (op & SLJIT_F32_OP)+ return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));+ return SLJIT_SUCCESS;++#endif+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));+ src2 = TMP_FREG2;+ }++ return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r;++ CHECK_ERROR();++ SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)+ op ^= SLJIT_F32_OP;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_CONV_F64_FROM_F32:+ op ^= SLJIT_F32_OP;+ if (op & SLJIT_F32_OP) {+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));+ break;+ }+ /* Fall through. */+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (dst_r != TMP_FREG1)+ FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));+ break;+ }++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));+ src2 = TMP_FREG2;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));+ break;++ case SLJIT_SUB_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));+ break;++ case SLJIT_MUL_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));+ break;++ case SLJIT_DIV_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));+ break;+ }++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));++ return SLJIT_SUCCESS;+}++#undef SELECT_FOP++/* --------------------------------------------------------------------- */+/* Other instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ if (FAST_IS_REG(dst))+ return push_inst(compiler, MFLR | D(dst));++ /* Memory. */+ FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));+ return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++static sljit_ins get_bo_bi_flags(sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ return (12 << 21) | (2 << 16);++ case SLJIT_NOT_EQUAL:+ return (4 << 21) | (2 << 16);++ case SLJIT_LESS:+ case SLJIT_SIG_LESS:+ return (12 << 21) | (0 << 16);++ case SLJIT_GREATER_EQUAL:+ case SLJIT_SIG_GREATER_EQUAL:+ return (4 << 21) | (0 << 16);++ case SLJIT_GREATER:+ case SLJIT_SIG_GREATER:+ return (12 << 21) | (1 << 16);++ case SLJIT_LESS_EQUAL:+ case SLJIT_SIG_LESS_EQUAL:+ return (4 << 21) | (1 << 16);++ case SLJIT_LESS_F64:+ return (12 << 21) | ((4 + 0) << 16);++ case SLJIT_GREATER_EQUAL_F64:+ return (4 << 21) | ((4 + 0) << 16);++ case SLJIT_GREATER_F64:+ return (12 << 21) | ((4 + 1) << 16);++ case SLJIT_LESS_EQUAL_F64:+ return (4 << 21) | ((4 + 1) << 16);++ case SLJIT_OVERFLOW:+ case SLJIT_MUL_OVERFLOW:+ return (12 << 21) | (3 << 16);++ case SLJIT_NOT_OVERFLOW:+ case SLJIT_MUL_NOT_OVERFLOW:+ return (4 << 21) | (3 << 16);++ case SLJIT_EQUAL_F64:+ return (12 << 21) | ((4 + 2) << 16);++ case SLJIT_NOT_EQUAL_F64:+ return (4 << 21) | ((4 + 2) << 16);++ case SLJIT_UNORDERED_F64:+ return (12 << 21) | ((4 + 3) << 16);++ case SLJIT_ORDERED_F64:+ return (4 << 21) | ((4 + 3) << 16);++ default:+ SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);+ return (20 << 21);+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;+ sljit_ins bo_bi_flags;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ bo_bi_flags = get_bo_bi_flags(type & 0xff);+ if (!bo_bi_flags)+ return NULL;++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ /* In PPC, we don't need to touch the arguments. */+ if (type < SLJIT_JUMP)+ jump->flags |= IS_COND;+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)+ if (type >= SLJIT_CALL)+ jump->flags |= IS_CALL;+#endif++ PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));+ PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG)));+ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));+#endif++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_jump(compiler, type);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ struct sljit_jump *jump = NULL;+ sljit_s32 src_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ if (FAST_IS_REG(src)) {+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)+ if (type >= SLJIT_CALL) {+ FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));+ src_r = TMP_CALL_REG;+ }+ else+ src_r = src;+#else+ src_r = src;+#endif+ } else if (src & SLJIT_IMM) {+ /* These jumps are converted to jump/call instructions when possible. */+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR);+ jump->u.target = srcw;+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)+ if (type >= SLJIT_CALL)+ jump->flags |= IS_CALL;+#endif+ FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));+ src_r = TMP_CALL_REG;+ }+ else {+ FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));+ src_r = TMP_CALL_REG;+ }++ FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));+ if (jump)+ jump->addr = compiler->size;+ return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));+ src = TMP_CALL_REG;+ }++ FAIL_IF(call_with_args(compiler, arg_types, &src));+#endif++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_ijump(compiler, type, src, srcw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 type)+{+ sljit_s32 reg, input_flags, cr_bit, invert;+ sljit_s32 saved_op = op;+ sljit_sw saved_dstw = dstw;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ input_flags = (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA;+#else+ input_flags = WORD_DATA;+#endif++ op = GET_OPCODE(op);+ reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;++ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))+ FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));++ invert = 0;+ cr_bit = 0;++ switch (type & 0xff) {+ case SLJIT_LESS:+ case SLJIT_SIG_LESS:+ break;++ case SLJIT_GREATER_EQUAL:+ case SLJIT_SIG_GREATER_EQUAL:+ invert = 1;+ break;++ case SLJIT_GREATER:+ case SLJIT_SIG_GREATER:+ cr_bit = 1;+ break;++ case SLJIT_LESS_EQUAL:+ case SLJIT_SIG_LESS_EQUAL:+ cr_bit = 1;+ invert = 1;+ break;++ case SLJIT_EQUAL:+ cr_bit = 2;+ break;++ case SLJIT_NOT_EQUAL:+ cr_bit = 2;+ invert = 1;+ break;++ case SLJIT_OVERFLOW:+ case SLJIT_MUL_OVERFLOW:+ cr_bit = 3;+ break;++ case SLJIT_NOT_OVERFLOW:+ case SLJIT_MUL_NOT_OVERFLOW:+ cr_bit = 3;+ invert = 1;+ break;++ case SLJIT_LESS_F64:+ cr_bit = 4 + 0;+ break;++ case SLJIT_GREATER_EQUAL_F64:+ cr_bit = 4 + 0;+ invert = 1;+ break;++ case SLJIT_GREATER_F64:+ cr_bit = 4 + 1;+ break;++ case SLJIT_LESS_EQUAL_F64:+ cr_bit = 4 + 1;+ invert = 1;+ break;++ case SLJIT_EQUAL_F64:+ cr_bit = 4 + 2;+ break;++ case SLJIT_NOT_EQUAL_F64:+ cr_bit = 4 + 2;+ invert = 1;+ break;++ case SLJIT_UNORDERED_F64:+ cr_bit = 4 + 3;+ break;++ case SLJIT_ORDERED_F64:+ cr_bit = 4 + 3;+ invert = 1;+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++ FAIL_IF(push_inst(compiler, MFCR | D(reg)));+ FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + (cr_bit)) << 11) | (31 << 6) | (31 << 1)));++ if (invert)+ FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));++ if (op < SLJIT_ADD) {+ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;+ return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);+ }++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ if (dst & SLJIT_MEM)+ return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);+ return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));++ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 reg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 mem_flags;+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));++ if (type & SLJIT_MEM_POST)+ return SLJIT_ERR_UNSUPPORTED;++ switch (type & 0xff) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+#endif+ mem_flags = WORD_DATA;+ break;++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ case SLJIT_MOV_U32:+ mem_flags = INT_DATA;+ break;++ case SLJIT_MOV_S32:+ mem_flags = INT_DATA;++ if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_I32_OP)) {+ if (mem & OFFS_REG_MASK)+ mem_flags |= SIGNED_DATA;+ else+ return SLJIT_ERR_UNSUPPORTED;+ }+ break;+#endif++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ mem_flags = BYTE_DATA;+ break;++ case SLJIT_MOV_U16:+ mem_flags = HALF_DATA;+ break;++ case SLJIT_MOV_S16:+ mem_flags = HALF_DATA | SIGNED_DATA;+ break;++ default:+ SLJIT_UNREACHABLE();+ mem_flags = WORD_DATA;+ break;+ }++ if (!(type & SLJIT_MEM_STORE))+ mem_flags |= LOAD_DATA;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ if (memw != 0)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ inst = updated_data_transfer_insts[mem_flags | INDEXED];+ FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));+ }+ else {+ if (memw > SIMM_MAX || memw < SIMM_MIN)+ return SLJIT_ERR_UNSUPPORTED;++ inst = updated_data_transfer_insts[mem_flags];++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)+ return SLJIT_ERR_UNSUPPORTED;+#endif++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));+ }++ if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)+ return push_inst(compiler, EXTSB | S(reg) | A(reg));+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 freg,+ sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 mem_flags;+ sljit_ins inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));++ if (type & SLJIT_MEM_POST)+ return SLJIT_ERR_UNSUPPORTED;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ if (memw != 0)+ return SLJIT_ERR_UNSUPPORTED;+ }+ else {+ if (memw > SIMM_MAX || memw < SIMM_MIN)+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (type & SLJIT_MEM_SUPP)+ return SLJIT_SUCCESS;++ mem_flags = FLOAT_DATA(type);++ if (!(type & SLJIT_MEM_STORE))+ mem_flags |= LOAD_DATA;++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ inst = updated_data_transfer_insts[mem_flags | INDEXED];+ return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));+ }++ inst = updated_data_transfer_insts[mem_flags];+ return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_put_label *put_label;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));+ PTR_FAIL_IF(!put_label);+ set_put_label(put_label, compiler, 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ PTR_FAIL_IF(emit_const(compiler, dst_r, 0));+#else+ PTR_FAIL_IF(push_inst(compiler, dst_r));+ compiler->size += 4;+#endif++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));++ return put_label;+}
+ src/c/pcre2/src/sljit/sljitNativeSPARC_32.c view
@@ -0,0 +1,283 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw imm)+{+ if (imm <= SIMM_MAX && imm >= SIMM_MIN)+ return push_inst(compiler, OR | D(dst) | S1(0) | IMM(imm), DR(dst));++ FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((imm >> 10) & 0x3fffff), DR(dst)));+ return (imm & 0x3ff) ? push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (imm & 0x3ff), DR(dst)) : SLJIT_SUCCESS;+}++#define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2))++static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,+ sljit_s32 dst, sljit_s32 src1, sljit_sw src2)+{+ SLJIT_COMPILE_ASSERT(ICC_IS_SET == SET_FLAGS, icc_is_set_and_set_flags_must_be_the_same);++ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if (dst != src2)+ return push_inst(compiler, OR | D(dst) | S1(0) | S2(src2), DR(dst));+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_U8)+ return push_inst(compiler, AND | D(dst) | S1(src2) | IMM(0xff), DR(dst));+ FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(24), DR(dst)));+ return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst));+ }+ else if (dst != src2)+ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(16), DR(dst)));+ return push_inst(compiler, (op == SLJIT_MOV_S16 ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));+ }+ else if (dst != src2)+ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;++ case SLJIT_NOT:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ return push_inst(compiler, XNOR | (flags & SET_FLAGS) | D(dst) | S1(0) | S2(src2), DR(dst) | (flags & SET_FLAGS));++ case SLJIT_CLZ:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS));+ FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst)));++ /* Loop. */+ FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));+ FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS));+ return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS);++ case SLJIT_ADD:+ return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));++ case SLJIT_ADDC:+ return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));++ case SLJIT_SUB:+ return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));++ case SLJIT_SUBC:+ return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));++ case SLJIT_MUL:+ FAIL_IF(push_inst(compiler, SMUL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));+ if (!(flags & SET_FLAGS))+ return SLJIT_SUCCESS;+ FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(dst) | IMM(31), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, RDY | D(TMP_LINK), DR(TMP_LINK)));+ return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_LINK), MOVABLE_INS | SET_FLAGS);++ case SLJIT_AND:+ return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));++ case SLJIT_OR:+ return push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));++ case SLJIT_XOR:+ return push_inst(compiler, XOR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));++ case SLJIT_SHL:+ FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));+ return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);++ case SLJIT_LSHR:+ FAIL_IF(push_inst(compiler, SRL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));+ return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);++ case SLJIT_ASHR:+ FAIL_IF(push_inst(compiler, SRA | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));+ return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)+{+ sljit_s32 reg_index = 8;+ sljit_s32 word_reg_index = 8;+ sljit_s32 float_arg_index = 1;+ sljit_s32 double_arg_count = 0;+ sljit_s32 float_offset = (16 + 6) * sizeof(sljit_sw);+ sljit_s32 types = 0;+ sljit_s32 reg = 0;+ sljit_s32 move_to_tmp2 = 0;++ if (src)+ reg = reg_map[*src & REG_MASK];++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);++ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ float_arg_index++;+ if (reg_index == reg)+ move_to_tmp2 = 1;+ reg_index++;+ break;+ case SLJIT_ARG_TYPE_F64:+ float_arg_index++;+ double_arg_count++;+ if (reg_index == reg || reg_index + 1 == reg)+ move_to_tmp2 = 1;+ reg_index += 2;+ break;+ default:+ if (reg_index != word_reg_index && reg_index < 14 && reg_index == reg)+ move_to_tmp2 = 1;+ reg_index++;+ word_reg_index++;+ break;+ }++ if (move_to_tmp2) {+ move_to_tmp2 = 0;+ if (reg < 14)+ FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2A(reg), DR(TMP_REG1)));+ *src = TMP_REG1;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ arg_types = types;++ while (arg_types) {+ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ float_arg_index--;+ FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));+ float_offset -= sizeof(sljit_f64);+ break;+ case SLJIT_ARG_TYPE_F64:+ float_arg_index--;+ if (float_arg_index == 4 && double_arg_count == 4) {+ FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM((16 + 7) * sizeof(sljit_sw)), MOVABLE_INS));+ FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | (1 << 25) | S1(SLJIT_SP) | IMM((16 + 8) * sizeof(sljit_sw)), MOVABLE_INS));+ }+ else+ FAIL_IF(push_inst(compiler, STDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));+ float_offset -= sizeof(sljit_f64);+ break;+ default:+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ float_offset = (16 + 6) * sizeof(sljit_sw);++ while (types) {+ switch (types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ reg_index--;+ if (reg_index < 14)+ FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));+ float_offset -= sizeof(sljit_f64);+ break;+ case SLJIT_ARG_TYPE_F64:+ reg_index -= 2;+ if (reg_index < 14) {+ if ((reg_index & 0x1) != 0) {+ FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));+ if (reg_index < 13)+ FAIL_IF(push_inst(compiler, LDUW | DA(reg_index + 1) | S1(SLJIT_SP) | IMM(float_offset + sizeof(sljit_sw)), reg_index + 1));+ }+ else + FAIL_IF(push_inst(compiler, LDD | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));+ }+ float_offset -= sizeof(sljit_f64);+ break;+ default:+ reg_index--;+ word_reg_index--;++ if (reg_index != word_reg_index) {+ if (reg_index < 14)+ FAIL_IF(push_inst(compiler, OR | DA(reg_index) | S1(0) | S2A(word_reg_index), reg_index));+ else+ FAIL_IF(push_inst(compiler, STW | DA(word_reg_index) | S1(SLJIT_SP) | IMM(92), word_reg_index));+ }+ break;+ }++ types >>= SLJIT_DEF_SHIFT;+ }++ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)+{+ FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((init_value >> 10) & 0x3fffff), DR(dst)));+ return push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (init_value & 0x3ff), DR(dst));+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ sljit_ins *inst = (sljit_ins *)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000));+ inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff);+ inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_set_jump_addr(addr, new_constant, executable_offset);+}
+ src/c/pcre2/src/sljit/sljitNativeSPARC_common.c view
@@ -0,0 +1,1554 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+ return "SPARC" SLJIT_CPUINFO;+}++/* Length of an instruction word+ Both for sparc-32 and sparc-64 */+typedef sljit_u32 sljit_ins;++#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)++static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)+{+#if defined(__SUNPRO_C) && __SUNPRO_C < 0x590+ __asm (+ /* if (from == to) return */+ "cmp %i0, %i1\n"+ "be .leave\n"+ "nop\n"++ /* loop until from >= to */+ ".mainloop:\n"+ "flush %i0\n"+ "add %i0, 8, %i0\n"+ "cmp %i0, %i1\n"+ "bcs .mainloop\n"+ "nop\n"++ /* The comparison was done above. */+ "bne .leave\n"+ /* nop is not necessary here, since the+ sub operation has no side effect. */+ "sub %i0, 4, %i0\n"+ "flush %i0\n"+ ".leave:"+ );+#else+ if (SLJIT_UNLIKELY(from == to))+ return;++ do {+ __asm__ volatile (+ "flush %0\n"+ : : "r"(from)+ );+ /* Operates at least on doubleword. */+ from += 2;+ } while (from < to);++ if (from == to) {+ /* Flush the last word. */+ from --;+ __asm__ volatile (+ "flush %0\n"+ : : "r"(from)+ );+ }+#endif+}++#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */++/* TMP_REG2 is not used by getput_arg */+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)+#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)+/* This register is modified by calls, which affects the instruction+ in the delay slot if it is used as a source register. */+#define TMP_LINK (SLJIT_NUMBER_OF_REGISTERS + 5)++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {+ 0, 8, 9, 10, 11, 29, 28, 27, 23, 22, 21, 20, 19, 18, 17, 16, 26, 25, 24, 14, 1, 12, 13, 15+};++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {+ 0, 0, 2, 4, 6, 8, 10, 12, 14+};++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++#define D(d) (reg_map[d] << 25)+#define FD(d) (freg_map[d] << 25)+#define FDN(d) ((freg_map[d] | 0x1) << 25)+#define DA(d) ((d) << 25)+#define S1(s1) (reg_map[s1] << 14)+#define FS1(s1) (freg_map[s1] << 14)+#define S1A(s1) ((s1) << 14)+#define S2(s2) (reg_map[s2])+#define FS2(s2) (freg_map[s2])+#define FS2N(s2) (freg_map[s2] | 0x1)+#define S2A(s2) (s2)+#define IMM_ARG 0x2000+#define DOP(op) ((op) << 5)+#define IMM(imm) (((imm) & 0x1fff) | IMM_ARG)++#define DR(dr) (reg_map[dr])+#define OPC1(opcode) ((opcode) << 30)+#define OPC2(opcode) ((opcode) << 22)+#define OPC3(opcode) ((opcode) << 19)+#define SET_FLAGS OPC3(0x10)++#define ADD (OPC1(0x2) | OPC3(0x00))+#define ADDC (OPC1(0x2) | OPC3(0x08))+#define AND (OPC1(0x2) | OPC3(0x01))+#define ANDN (OPC1(0x2) | OPC3(0x05))+#define CALL (OPC1(0x1))+#define FABSS (OPC1(0x2) | OPC3(0x34) | DOP(0x09))+#define FADDD (OPC1(0x2) | OPC3(0x34) | DOP(0x42))+#define FADDS (OPC1(0x2) | OPC3(0x34) | DOP(0x41))+#define FCMPD (OPC1(0x2) | OPC3(0x35) | DOP(0x52))+#define FCMPS (OPC1(0x2) | OPC3(0x35) | DOP(0x51))+#define FDIVD (OPC1(0x2) | OPC3(0x34) | DOP(0x4e))+#define FDIVS (OPC1(0x2) | OPC3(0x34) | DOP(0x4d))+#define FDTOI (OPC1(0x2) | OPC3(0x34) | DOP(0xd2))+#define FDTOS (OPC1(0x2) | OPC3(0x34) | DOP(0xc6))+#define FITOD (OPC1(0x2) | OPC3(0x34) | DOP(0xc8))+#define FITOS (OPC1(0x2) | OPC3(0x34) | DOP(0xc4))+#define FMOVS (OPC1(0x2) | OPC3(0x34) | DOP(0x01))+#define FMULD (OPC1(0x2) | OPC3(0x34) | DOP(0x4a))+#define FMULS (OPC1(0x2) | OPC3(0x34) | DOP(0x49))+#define FNEGS (OPC1(0x2) | OPC3(0x34) | DOP(0x05))+#define FSTOD (OPC1(0x2) | OPC3(0x34) | DOP(0xc9))+#define FSTOI (OPC1(0x2) | OPC3(0x34) | DOP(0xd1))+#define FSUBD (OPC1(0x2) | OPC3(0x34) | DOP(0x46))+#define FSUBS (OPC1(0x2) | OPC3(0x34) | DOP(0x45))+#define JMPL (OPC1(0x2) | OPC3(0x38))+#define LDD (OPC1(0x3) | OPC3(0x03))+#define LDUW (OPC1(0x3) | OPC3(0x00))+#define NOP (OPC1(0x0) | OPC2(0x04))+#define OR (OPC1(0x2) | OPC3(0x02))+#define ORN (OPC1(0x2) | OPC3(0x06))+#define RDY (OPC1(0x2) | OPC3(0x28) | S1A(0))+#define RESTORE (OPC1(0x2) | OPC3(0x3d))+#define SAVE (OPC1(0x2) | OPC3(0x3c))+#define SETHI (OPC1(0x0) | OPC2(0x04))+#define SLL (OPC1(0x2) | OPC3(0x25))+#define SLLX (OPC1(0x2) | OPC3(0x25) | (1 << 12))+#define SRA (OPC1(0x2) | OPC3(0x27))+#define SRAX (OPC1(0x2) | OPC3(0x27) | (1 << 12))+#define SRL (OPC1(0x2) | OPC3(0x26))+#define SRLX (OPC1(0x2) | OPC3(0x26) | (1 << 12))+#define STDF (OPC1(0x3) | OPC3(0x27))+#define STF (OPC1(0x3) | OPC3(0x24))+#define STW (OPC1(0x3) | OPC3(0x04))+#define SUB (OPC1(0x2) | OPC3(0x04))+#define SUBC (OPC1(0x2) | OPC3(0x0c))+#define TA (OPC1(0x2) | OPC3(0x3a) | (8 << 25))+#define WRY (OPC1(0x2) | OPC3(0x30) | DA(0))+#define XOR (OPC1(0x2) | OPC3(0x03))+#define XNOR (OPC1(0x2) | OPC3(0x07))++#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+#define MAX_DISP (0x1fffff)+#define MIN_DISP (-0x200000)+#define DISP_MASK (0x3fffff)++#define BICC (OPC1(0x0) | OPC2(0x2))+#define FBFCC (OPC1(0x0) | OPC2(0x6))+#define SLL_W SLL+#define SDIV (OPC1(0x2) | OPC3(0x0f))+#define SMUL (OPC1(0x2) | OPC3(0x0b))+#define UDIV (OPC1(0x2) | OPC3(0x0e))+#define UMUL (OPC1(0x2) | OPC3(0x0a))+#else+#define SLL_W SLLX+#endif++#define SIMM_MAX (0x0fff)+#define SIMM_MIN (-0x1000)++/* dest_reg is the absolute name of the register+ Useful for reordering instructions in the delay slot. */+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)+{+ sljit_ins *ptr;+ SLJIT_ASSERT((delay_slot & DST_INS_MASK) == UNMOVABLE_INS+ || (delay_slot & DST_INS_MASK) == MOVABLE_INS+ || (delay_slot & DST_INS_MASK) == ((ins >> 25) & 0x1f));+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ *ptr = ins;+ compiler->size++;+ compiler->delay_slot = delay_slot;+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_sw diff;+ sljit_uw target_addr;+ sljit_ins *inst;+ sljit_ins saved_inst;++ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ return code_ptr;++ if (jump->flags & JUMP_ADDR)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;+ }+ inst = (sljit_ins*)jump->addr;++#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ if (jump->flags & IS_CALL) {+ /* Call is always patchable on sparc 32. */+ jump->flags |= PATCH_CALL;+ if (jump->flags & IS_MOVABLE) {+ inst[0] = inst[-1];+ inst[-1] = CALL;+ jump->addr -= sizeof(sljit_ins);+ return inst;+ }+ inst[0] = CALL;+ inst[1] = NOP;+ return inst + 1;+ }+#else+ /* Both calls and BPr instructions shall not pass this point. */+#error "Implementation required"+#endif++ if (jump->flags & IS_COND)+ inst--;++ diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1) - executable_offset) >> 2;++ if (jump->flags & IS_MOVABLE) {+ if (diff <= MAX_DISP && diff >= MIN_DISP) {+ jump->flags |= PATCH_B;+ inst--;+ if (jump->flags & IS_COND) {+ saved_inst = inst[0];+ inst[0] = inst[1] ^ (1 << 28);+ inst[1] = saved_inst;+ } else {+ inst[1] = inst[0];+ inst[0] = BICC | DA(0x8);+ }+ jump->addr = (sljit_uw)inst;+ return inst + 1;+ }+ }++ diff += sizeof(sljit_ins);++ if (diff <= MAX_DISP && diff >= MIN_DISP) {+ jump->flags |= PATCH_B;+ if (jump->flags & IS_COND)+ inst[0] ^= (1 << 28);+ else+ inst[0] = BICC | DA(0x8);+ inst[1] = NOP;+ jump->addr = (sljit_uw)inst;+ return inst + 1;+ }++ return code_ptr;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ sljit_uw next_addr;+ sljit_sw executable_offset;+ sljit_uw addr;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ struct sljit_put_label *put_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));+ reverse_buf(compiler);++ code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);+ PTR_FAIL_WITH_EXEC_IF(code);+ buf = compiler->buf;++ code_ptr = code;+ word_count = 0;+ next_addr = 0;+ executable_offset = SLJIT_EXEC_OFFSET(code);++ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ put_label = compiler->put_labels;++ do {+ buf_ptr = (sljit_ins*)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 2);+ do {+ *code_ptr = *buf_ptr++;+ if (next_addr == word_count) {+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);++ /* These structures are ordered by their address. */+ if (label && label->size == word_count) {+ /* Just recording the address. */+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = code_ptr - code;+ label = label->next;+ }+ if (jump && jump->addr == word_count) {+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ jump->addr = (sljit_uw)(code_ptr - 3);+#else+ jump->addr = (sljit_uw)(code_ptr - 6);+#endif+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);+ jump = jump->next;+ }+ if (const_ && const_->addr == word_count) {+ /* Just recording the address. */+ const_->addr = (sljit_uw)code_ptr;+ const_ = const_->next;+ }+ if (put_label && put_label->addr == word_count) {+ SLJIT_ASSERT(put_label->label);+ put_label->addr = (sljit_uw)code_ptr;+ put_label = put_label->next;+ }+ next_addr = compute_next_addr(label, jump, const_, put_label);+ }+ code_ptr ++;+ word_count ++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = code_ptr - code;+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(!put_label);+ SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size);++ jump = compiler->jumps;+ while (jump) {+ do {+ addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;+ buf_ptr = (sljit_ins *)jump->addr;++ if (jump->flags & PATCH_CALL) {+ addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;+ SLJIT_ASSERT((sljit_sw)addr <= 0x1fffffff && (sljit_sw)addr >= -0x20000000);+ buf_ptr[0] = CALL | (addr & 0x3fffffff);+ break;+ }+ if (jump->flags & PATCH_B) {+ addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;+ SLJIT_ASSERT((sljit_sw)addr <= MAX_DISP && (sljit_sw)addr >= MIN_DISP);+ buf_ptr[0] = (buf_ptr[0] & ~DISP_MASK) | (addr & DISP_MASK);+ break;+ }++ /* Set the fields of immediate loads. */+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));+ buf_ptr[0] |= (addr >> 10) & 0x3fffff;+ buf_ptr[1] |= addr & 0x3ff;+#else+#error "Implementation required"+#endif+ } while (0);+ jump = jump->next;+ }++ put_label = compiler->put_labels;+ while (put_label) {+ addr = put_label->label->addr;+ buf_ptr = (sljit_ins *)put_label->addr;++#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));+ buf_ptr[0] |= (addr >> 10) & 0x3fffff;+ buf_ptr[1] |= addr & 0x3ff;+#else+#error "Implementation required"+#endif+ put_label = put_label->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);++ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ SLJIT_CACHE_FLUSH(code, code_ptr);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ return code;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ switch (feature_type) {+ case SLJIT_HAS_FPU:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return SLJIT_IS_FPU_AVAILABLE;+#else+ /* Available by default. */+ return 1;+#endif++ case SLJIT_HAS_ZERO_REGISTER:+ return 1;++#if (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)+ case SLJIT_HAS_CMOV:+ return 1;+#endif++ default:+ return 0;+ }+}++/* --------------------------------------------------------------------- */+/* Entry, exit */+/* --------------------------------------------------------------------- */++/* Creates an index in data_transfer_insts array. */+#define LOAD_DATA 0x01+#define WORD_DATA 0x00+#define BYTE_DATA 0x02+#define HALF_DATA 0x04+#define INT_DATA 0x06+#define SIGNED_DATA 0x08+/* Separates integer and floating point registers */+#define GPR_REG 0x0f+#define DOUBLE_DATA 0x10+#define SINGLE_DATA 0x12++#define MEM_MASK 0x1f++#define ARG_TEST 0x00020+#define ALT_KEEP_CACHE 0x00040+#define CUMULATIVE_OP 0x00080+#define IMM_OP 0x00100+#define SRC2_IMM 0x00200++#define REG_DEST 0x00400+#define REG2_SOURCE 0x00800+#define SLOW_SRC1 0x01000+#define SLOW_SRC2 0x02000+#define SLOW_DEST 0x04000++/* SET_FLAGS (0x10 << 19) also belong here! */++#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+#include "sljitNativeSPARC_32.c"+#else+#include "sljitNativeSPARC_64.c"+#endif++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7;+ compiler->local_size = local_size;++ if (local_size <= SIMM_MAX) {+ FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_SP) | S1(SLJIT_SP) | IMM(-local_size), UNMOVABLE_INS));+ }+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, -local_size));+ FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_SP) | S1(SLJIT_SP) | S2(TMP_REG1), UNMOVABLE_INS));+ }++ /* Arguments are in their appropriate registers. */++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7;+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));++ if (op != SLJIT_MOV || !FAST_IS_REG(src)) {+ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));+ src = SLJIT_R0;+ }++ FAIL_IF(push_inst(compiler, JMPL | D(0) | S1A(31) | IMM(8), UNMOVABLE_INS));+ return push_inst(compiler, RESTORE | D(SLJIT_R0) | S1(src) | S2(0), UNMOVABLE_INS);+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+#define ARCH_32_64(a, b) a+#else+#define ARCH_32_64(a, b) b+#endif++static const sljit_ins data_transfer_insts[16 + 4] = {+/* u w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */),+/* u w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */),+/* u b s */ OPC1(3) | OPC3(0x05) /* stb */,+/* u b l */ OPC1(3) | OPC3(0x01) /* ldub */,+/* u h s */ OPC1(3) | OPC3(0x06) /* sth */,+/* u h l */ OPC1(3) | OPC3(0x02) /* lduh */,+/* u i s */ OPC1(3) | OPC3(0x04) /* stw */,+/* u i l */ OPC1(3) | OPC3(0x00) /* lduw */,++/* s w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */),+/* s w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */),+/* s b s */ OPC1(3) | OPC3(0x05) /* stb */,+/* s b l */ OPC1(3) | OPC3(0x09) /* ldsb */,+/* s h s */ OPC1(3) | OPC3(0x06) /* sth */,+/* s h l */ OPC1(3) | OPC3(0x0a) /* ldsh */,+/* s i s */ OPC1(3) | OPC3(0x04) /* stw */,+/* s i l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x08) /* ldsw */),++/* d s */ OPC1(3) | OPC3(0x27),+/* d l */ OPC1(3) | OPC3(0x23),+/* s s */ OPC1(3) | OPC3(0x24),+/* s l */ OPC1(3) | OPC3(0x20),+};++#undef ARCH_32_64++/* Can perform an operation using at most 1 instruction. */+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ SLJIT_ASSERT(arg & SLJIT_MEM);++ if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN)+ || ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) {+ /* Works for both absoulte and relative addresses (immediate case). */+ if (SLJIT_UNLIKELY(flags & ARG_TEST))+ return 1;+ FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK]+ | ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg))+ | S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)),+ ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS));+ return -1;+ }+ return 0;+}++/* See getput_arg below.+ Note: can_cache is called only for binary operators. Those+ operators always uses word arguments without write back. */+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)+{+ SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));++ /* Simple operation except for updates. */+ if (arg & OFFS_REG_MASK) {+ argw &= 0x3;+ SLJIT_ASSERT(argw);+ next_argw &= 0x3;+ if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == next_argw)+ return 1;+ return 0;+ }++ if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN))+ return 1;+ return 0;+}++/* Emit the necessary instructions. See can_cache above. */+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)+{+ sljit_s32 base, arg2, delay_slot;+ sljit_ins dest;++ SLJIT_ASSERT(arg & SLJIT_MEM);+ if (!(next_arg & SLJIT_MEM)) {+ next_arg = 0;+ next_argw = 0;+ }++ base = arg & REG_MASK;+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ /* Using the cache. */+ if (((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) && (argw == compiler->cache_argw))+ arg2 = TMP_REG3;+ else {+ if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == (next_argw & 0x3)) {+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);+ compiler->cache_argw = argw;+ arg2 = TMP_REG3;+ }+ else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base && reg != OFFS_REG(arg))+ arg2 = reg;+ else /* It must be a mov operation, so tmp1 must be free to use. */+ arg2 = TMP_REG1;+ FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1(OFFS_REG(arg)) | IMM_ARG | argw, DR(arg2)));+ }+ }+ else {+ /* Using the cache. */+ if ((compiler->cache_arg == SLJIT_MEM) && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {+ if (argw != compiler->cache_argw) {+ FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | S1(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));+ compiler->cache_argw = argw;+ }+ arg2 = TMP_REG3;+ } else {+ if ((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN) {+ compiler->cache_arg = SLJIT_MEM;+ compiler->cache_argw = argw;+ arg2 = TMP_REG3;+ }+ else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base)+ arg2 = reg;+ else /* It must be a mov operation, so tmp1 must be free to use. */+ arg2 = TMP_REG1;+ FAIL_IF(load_immediate(compiler, arg2, argw));+ }+ }++ dest = ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg));+ delay_slot = ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS;+ if (!base)+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(arg2) | IMM(0), delay_slot);+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot);+}++static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)+{+ if (getput_arg_fast(compiler, flags, reg, arg, argw))+ return compiler->error;+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+ return getput_arg(compiler, flags, reg, arg, argw, 0, 0);+}++static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)+{+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))+ return compiler->error;+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);+}++static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ /* arg1 goes to TMP_REG1 or src reg+ arg2 goes to TMP_REG2, imm or src reg+ TMP_REG3 can be used for caching+ result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */+ sljit_s32 dst_r = TMP_REG2;+ sljit_s32 src1_r;+ sljit_sw src2_r = 0;+ sljit_s32 sugg_src2_r = TMP_REG2;++ if (!(flags & ALT_KEEP_CACHE)) {+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+ }++ if (dst != SLJIT_UNUSED) {+ if (FAST_IS_REG(dst)) {+ dst_r = dst;+ flags |= REG_DEST;+ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)+ sugg_src2_r = dst_r;+ }+ else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))+ flags |= SLOW_DEST;+ }++ if (flags & IMM_OP) {+ if ((src2 & SLJIT_IMM) && src2w) {+ if (src2w <= SIMM_MAX && src2w >= SIMM_MIN) {+ flags |= SRC2_IMM;+ src2_r = src2w;+ }+ }+ if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {+ if (src1w <= SIMM_MAX && src1w >= SIMM_MIN) {+ flags |= SRC2_IMM;+ src2_r = src1w;++ /* And swap arguments. */+ src1 = src2;+ src1w = src2w;+ src2 = SLJIT_IMM;+ /* src2w = src2_r unneeded. */+ }+ }+ }++ /* Source 1. */+ if (FAST_IS_REG(src1))+ src1_r = src1;+ else if (src1 & SLJIT_IMM) {+ if (src1w) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));+ src1_r = TMP_REG1;+ }+ else+ src1_r = 0;+ }+ else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC1;+ src1_r = TMP_REG1;+ }++ /* Source 2. */+ if (FAST_IS_REG(src2)) {+ src2_r = src2;+ flags |= REG2_SOURCE;+ if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)+ dst_r = src2_r;+ }+ else if (src2 & SLJIT_IMM) {+ if (!(flags & SRC2_IMM)) {+ if (src2w) {+ FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));+ src2_r = sugg_src2_r;+ }+ else {+ src2_r = 0;+ if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM))+ dst_r = 0;+ }+ }+ }+ else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC2;+ src2_r = sugg_src2_r;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ SLJIT_ASSERT(src2_r == TMP_REG2);+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));+ }+ else {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));+ }+ }+ else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));++ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));++ if (dst & SLJIT_MEM) {+ if (!(flags & SLOW_DEST)) {+ getput_arg_fast(compiler, flags, dst_r, dst, dstw);+ return compiler->error;+ }+ return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_BREAKPOINT:+ return push_inst(compiler, TA, UNMOVABLE_INS);+ case SLJIT_NOP:+ return push_inst(compiler, NOP, UNMOVABLE_INS);+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? UMUL : SMUL) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));+ return push_inst(compiler, RDY | D(SLJIT_R1), DR(SLJIT_R1));+#else+#error "Implementation required"+#endif+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIVMOD_SW:+ case SLJIT_DIV_UW:+ case SLJIT_DIV_SW:+ SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ if ((op | 0x2) == SLJIT_DIV_UW)+ FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS));+ else {+ FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_R0) | IMM(31), DR(TMP_REG1)));+ FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS));+ }+ if (op <= SLJIT_DIVMOD_SW)+ FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2)));+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));+ if (op >= SLJIT_DIV_UW)+ return SLJIT_SUCCESS;+ FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1)));+ return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1));+#else+#error "Implementation required"+#endif+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOV_U32:+ return emit_op(compiler, SLJIT_MOV_U32, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOV_S32:+ return emit_op(compiler, SLJIT_MOV_S32, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOV_U8:+ return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);++ case SLJIT_MOV_S8:+ return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);++ case SLJIT_MOV_U16:+ return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);++ case SLJIT_MOV_S16:+ return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);++ case SLJIT_NOT:+ case SLJIT_CLZ:+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_NEG:+ return emit_op(compiler, SLJIT_SUB, flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))+ return SLJIT_SUCCESS;++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_ADD:+ case SLJIT_ADDC:+ case SLJIT_MUL:+ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SUB:+ case SLJIT_SUBC:+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SHL:+ case SLJIT_LSHR:+ case SLJIT_ASHR:+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ if (src2 & SLJIT_IMM)+ src2w &= 0x1f;+#else+ SLJIT_UNREACHABLE();+#endif+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src))+ FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK)));+ else+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw));++ FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS));+ return push_inst(compiler, NOP, UNMOVABLE_INS);+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(reg));+ return reg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));+ return freg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))+#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)+#define FLOAT_TMP_MEM_OFFSET (22 * sizeof(sljit_sw))++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));+ src = TMP_FREG1;+ }++ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOI, FDTOI) | FD(TMP_FREG1) | FS2(src), MOVABLE_INS));++ if (FAST_IS_REG(dst)) {+ FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));+ return emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET);+ }++ /* Store the integer value from a VFP register. */+ return emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, dst, dstw, 0, 0);+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)+ srcw = (sljit_s32)srcw;+#endif+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));+ src = TMP_REG1;+ srcw = 0;+ }++ if (FAST_IS_REG(src)) {+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));+ src = SLJIT_MEM1(SLJIT_SP);+ srcw = FLOAT_TMP_MEM_OFFSET;+ }++ FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FITOS, FITOD) | FD(dst_r) | FS2(TMP_FREG1), MOVABLE_INS));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));+ src1 = TMP_FREG1;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));+ src2 = TMP_FREG2;+ }++ return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | FS1(src1) | FS2(src2), FCC_IS_SET | MOVABLE_INS);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r;++ CHECK_ERROR();+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)+ op ^= SLJIT_F32_OP;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;++ if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));+ src = dst_r;+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_F64:+ if (src != dst_r) {+ if (dst_r != TMP_FREG1) {+ FAIL_IF(push_inst(compiler, FMOVS | FD(dst_r) | FS2(src), MOVABLE_INS));+ if (!(op & SLJIT_F32_OP))+ FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));+ }+ else+ dst_r = src;+ }+ break;+ case SLJIT_NEG_F64:+ FAIL_IF(push_inst(compiler, FNEGS | FD(dst_r) | FS2(src), MOVABLE_INS));+ if (dst_r != src && !(op & SLJIT_F32_OP))+ FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));+ break;+ case SLJIT_ABS_F64:+ FAIL_IF(push_inst(compiler, FABSS | FD(dst_r) | FS2(src), MOVABLE_INS));+ if (dst_r != src && !(op & SLJIT_F32_OP))+ FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));+ break;+ case SLJIT_CONV_F64_FROM_F32:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | FD(dst_r) | FS2(src), MOVABLE_INS));+ op ^= SLJIT_F32_OP;+ break;+ }++ if (dst & SLJIT_MEM)+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0));+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 dst_r, flags = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;++ if (src1 & SLJIT_MEM) {+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {+ FAIL_IF(compiler->error);+ src1 = TMP_FREG1;+ } else+ flags |= SLOW_SRC1;+ }++ if (src2 & SLJIT_MEM) {+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {+ FAIL_IF(compiler->error);+ src2 = TMP_FREG2;+ } else+ flags |= SLOW_SRC2;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));+ }+ else {+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));+ }+ }+ else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));++ if (flags & SLOW_SRC1)+ src1 = TMP_FREG1;+ if (flags & SLOW_SRC2)+ src2 = TMP_FREG2;++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));+ break;++ case SLJIT_SUB_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));+ break;++ case SLJIT_MUL_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));+ break;++ case SLJIT_DIV_F64:+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));+ break;+ }++ if (dst_r == TMP_FREG2)+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));++ return SLJIT_SUCCESS;+}++#undef FLOAT_DATA+#undef SELECT_FOP++/* --------------------------------------------------------------------- */+/* Other instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ if (FAST_IS_REG(dst))+ return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), UNMOVABLE_INS);++ /* Memory. */+ FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw));+ compiler->delay_slot = UNMOVABLE_INS;+ return SLJIT_SUCCESS;+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ compiler->delay_slot = UNMOVABLE_INS;+ return label;+}++static sljit_ins get_cc(sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_MUL_NOT_OVERFLOW:+ case SLJIT_NOT_EQUAL_F64: /* Unordered. */+ return DA(0x1);++ case SLJIT_NOT_EQUAL:+ case SLJIT_MUL_OVERFLOW:+ case SLJIT_EQUAL_F64:+ return DA(0x9);++ case SLJIT_LESS:+ case SLJIT_GREATER_F64: /* Unordered. */+ return DA(0x5);++ case SLJIT_GREATER_EQUAL:+ case SLJIT_LESS_EQUAL_F64:+ return DA(0xd);++ case SLJIT_GREATER:+ case SLJIT_GREATER_EQUAL_F64: /* Unordered. */+ return DA(0xc);++ case SLJIT_LESS_EQUAL:+ case SLJIT_LESS_F64:+ return DA(0x4);++ case SLJIT_SIG_LESS:+ return DA(0x3);++ case SLJIT_SIG_GREATER_EQUAL:+ return DA(0xb);++ case SLJIT_SIG_GREATER:+ return DA(0xa);++ case SLJIT_SIG_LESS_EQUAL:+ return DA(0x2);++ case SLJIT_OVERFLOW:+ case SLJIT_UNORDERED_F64:+ return DA(0x7);++ case SLJIT_NOT_OVERFLOW:+ case SLJIT_ORDERED_F64:+ return DA(0xf);++ default:+ SLJIT_UNREACHABLE();+ return DA(0x8);+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ if (type < SLJIT_EQUAL_F64) {+ jump->flags |= IS_COND;+ if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & ICC_IS_SET))+ jump->flags |= IS_MOVABLE;+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ PTR_FAIL_IF(push_inst(compiler, BICC | get_cc(type ^ 1) | 5, UNMOVABLE_INS));+#else+#error "Implementation required"+#endif+ }+ else if (type < SLJIT_JUMP) {+ jump->flags |= IS_COND;+ if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & FCC_IS_SET))+ jump->flags |= IS_MOVABLE;+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ PTR_FAIL_IF(push_inst(compiler, FBFCC | get_cc(type ^ 1) | 5, UNMOVABLE_INS));+#else+#error "Implementation required"+#endif+ }+ else {+ if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)+ jump->flags |= IS_MOVABLE;+ if (type >= SLJIT_FAST_CALL)+ jump->flags |= IS_CALL;+ }++ PTR_FAIL_IF(emit_const(compiler, TMP_REG1, 0));+ PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(TMP_REG1) | IMM(0), UNMOVABLE_INS));+ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_jump(compiler, type);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ struct sljit_jump *jump = NULL;+ sljit_s32 src_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ if (FAST_IS_REG(src))+ src_r = src;+ else if (src & SLJIT_IMM) {+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR);+ jump->u.target = srcw;++ if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)+ jump->flags |= IS_MOVABLE;+ if (type >= SLJIT_FAST_CALL)+ jump->flags |= IS_CALL;++ FAIL_IF(emit_const(compiler, TMP_REG1, 0));+ src_r = TMP_REG1;+ }+ else {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));+ src_r = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS));+ if (jump)+ jump->addr = compiler->size;+ return push_inst(compiler, NOP, UNMOVABLE_INS);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));+ src = TMP_REG1;+ }++ FAIL_IF(call_with_args(compiler, arg_types, &src));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_ijump(compiler, type, src, srcw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 type)+{+ sljit_s32 reg, flags = HAS_FLAGS(op) ? SET_FLAGS : 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ op = GET_OPCODE(op);+ reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;++ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));++ type &= 0xff;+ if (type < SLJIT_EQUAL_F64)+ FAIL_IF(push_inst(compiler, BICC | get_cc(type) | 3, UNMOVABLE_INS));+ else+ FAIL_IF(push_inst(compiler, FBFCC | get_cc(type) | 3, UNMOVABLE_INS));++ FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(1), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(0), UNMOVABLE_INS));++ if (op >= SLJIT_ADD) {+ flags |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;+ if (dst & SLJIT_MEM)+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);+ return emit_op(compiler, op, flags, dst, 0, dst, 0, TMP_REG2, 0);+ }++ if (!(dst & SLJIT_MEM))+ return SLJIT_SUCCESS;++ return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);+#else+#error "Implementation required"+#endif+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));++#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)+ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;+#else+#error "Implementation required"+#endif+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));+ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_put_label *put_label;+ sljit_s32 dst_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));+ PTR_FAIL_IF(!put_label);+ set_put_label(put_label, compiler, 0);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ PTR_FAIL_IF(emit_const(compiler, dst_r, 0));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));+ return put_label;+}
+ src/c/pcre2/src/sljit/sljitNativeTILEGX-encoder.c view
@@ -0,0 +1,10159 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved.+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/* This code is owned by Tilera Corporation, and distributed as part+ of multiple projects. In sljit, the code is under BSD licence. */++#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#define BFD_RELOC(x) R_##x++/* Special registers. */+#define TREG_LR 55+#define TREG_SN 56+#define TREG_ZERO 63++/* Canonical name of each register. */+const char *const tilegx_register_names[] =+{+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",+ "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",+ "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",+ "r48", "r49", "r50", "r51", "r52", "tp", "sp", "lr",+ "sn", "idn0", "idn1", "udn0", "udn1", "udn2", "udn3", "zero"+};++enum+{+ R_NONE = 0,+ R_TILEGX_NONE = 0,+ R_TILEGX_64 = 1,+ R_TILEGX_32 = 2,+ R_TILEGX_16 = 3,+ R_TILEGX_8 = 4,+ R_TILEGX_64_PCREL = 5,+ R_TILEGX_32_PCREL = 6,+ R_TILEGX_16_PCREL = 7,+ R_TILEGX_8_PCREL = 8,+ R_TILEGX_HW0 = 9,+ R_TILEGX_HW1 = 10,+ R_TILEGX_HW2 = 11,+ R_TILEGX_HW3 = 12,+ R_TILEGX_HW0_LAST = 13,+ R_TILEGX_HW1_LAST = 14,+ R_TILEGX_HW2_LAST = 15,+ R_TILEGX_COPY = 16,+ R_TILEGX_GLOB_DAT = 17,+ R_TILEGX_JMP_SLOT = 18,+ R_TILEGX_RELATIVE = 19,+ R_TILEGX_BROFF_X1 = 20,+ R_TILEGX_JUMPOFF_X1 = 21,+ R_TILEGX_JUMPOFF_X1_PLT = 22,+ R_TILEGX_IMM8_X0 = 23,+ R_TILEGX_IMM8_Y0 = 24,+ R_TILEGX_IMM8_X1 = 25,+ R_TILEGX_IMM8_Y1 = 26,+ R_TILEGX_DEST_IMM8_X1 = 27,+ R_TILEGX_MT_IMM14_X1 = 28,+ R_TILEGX_MF_IMM14_X1 = 29,+ R_TILEGX_MMSTART_X0 = 30,+ R_TILEGX_MMEND_X0 = 31,+ R_TILEGX_SHAMT_X0 = 32,+ R_TILEGX_SHAMT_X1 = 33,+ R_TILEGX_SHAMT_Y0 = 34,+ R_TILEGX_SHAMT_Y1 = 35,+ R_TILEGX_IMM16_X0_HW0 = 36,+ R_TILEGX_IMM16_X1_HW0 = 37,+ R_TILEGX_IMM16_X0_HW1 = 38,+ R_TILEGX_IMM16_X1_HW1 = 39,+ R_TILEGX_IMM16_X0_HW2 = 40,+ R_TILEGX_IMM16_X1_HW2 = 41,+ R_TILEGX_IMM16_X0_HW3 = 42,+ R_TILEGX_IMM16_X1_HW3 = 43,+ R_TILEGX_IMM16_X0_HW0_LAST = 44,+ R_TILEGX_IMM16_X1_HW0_LAST = 45,+ R_TILEGX_IMM16_X0_HW1_LAST = 46,+ R_TILEGX_IMM16_X1_HW1_LAST = 47,+ R_TILEGX_IMM16_X0_HW2_LAST = 48,+ R_TILEGX_IMM16_X1_HW2_LAST = 49,+ R_TILEGX_IMM16_X0_HW0_PCREL = 50,+ R_TILEGX_IMM16_X1_HW0_PCREL = 51,+ R_TILEGX_IMM16_X0_HW1_PCREL = 52,+ R_TILEGX_IMM16_X1_HW1_PCREL = 53,+ R_TILEGX_IMM16_X0_HW2_PCREL = 54,+ R_TILEGX_IMM16_X1_HW2_PCREL = 55,+ R_TILEGX_IMM16_X0_HW3_PCREL = 56,+ R_TILEGX_IMM16_X1_HW3_PCREL = 57,+ R_TILEGX_IMM16_X0_HW0_LAST_PCREL = 58,+ R_TILEGX_IMM16_X1_HW0_LAST_PCREL = 59,+ R_TILEGX_IMM16_X0_HW1_LAST_PCREL = 60,+ R_TILEGX_IMM16_X1_HW1_LAST_PCREL = 61,+ R_TILEGX_IMM16_X0_HW2_LAST_PCREL = 62,+ R_TILEGX_IMM16_X1_HW2_LAST_PCREL = 63,+ R_TILEGX_IMM16_X0_HW0_GOT = 64,+ R_TILEGX_IMM16_X1_HW0_GOT = 65,++ R_TILEGX_IMM16_X0_HW0_PLT_PCREL = 66,+ R_TILEGX_IMM16_X1_HW0_PLT_PCREL = 67,+ R_TILEGX_IMM16_X0_HW1_PLT_PCREL = 68,+ R_TILEGX_IMM16_X1_HW1_PLT_PCREL = 69,+ R_TILEGX_IMM16_X0_HW2_PLT_PCREL = 70,+ R_TILEGX_IMM16_X1_HW2_PLT_PCREL = 71,++ R_TILEGX_IMM16_X0_HW0_LAST_GOT = 72,+ R_TILEGX_IMM16_X1_HW0_LAST_GOT = 73,+ R_TILEGX_IMM16_X0_HW1_LAST_GOT = 74,+ R_TILEGX_IMM16_X1_HW1_LAST_GOT = 75,+ R_TILEGX_IMM16_X0_HW0_TLS_GD = 78,+ R_TILEGX_IMM16_X1_HW0_TLS_GD = 79,+ R_TILEGX_IMM16_X0_HW0_TLS_LE = 80,+ R_TILEGX_IMM16_X1_HW0_TLS_LE = 81,+ R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE = 82,+ R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE = 83,+ R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE = 84,+ R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE = 85,+ R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD = 86,+ R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD = 87,+ R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD = 88,+ R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD = 89,+ R_TILEGX_IMM16_X0_HW0_TLS_IE = 92,+ R_TILEGX_IMM16_X1_HW0_TLS_IE = 93,++ R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL = 94,+ R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL = 95,+ R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL = 96,+ R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL = 97,+ R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL = 98,+ R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL = 99,++ R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE = 100,+ R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE = 101,+ R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE = 102,+ R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE = 103,+ R_TILEGX_TLS_DTPMOD64 = 106,+ R_TILEGX_TLS_DTPOFF64 = 107,+ R_TILEGX_TLS_TPOFF64 = 108,+ R_TILEGX_TLS_DTPMOD32 = 109,+ R_TILEGX_TLS_DTPOFF32 = 110,+ R_TILEGX_TLS_TPOFF32 = 111,+ R_TILEGX_TLS_GD_CALL = 112,+ R_TILEGX_IMM8_X0_TLS_GD_ADD = 113,+ R_TILEGX_IMM8_X1_TLS_GD_ADD = 114,+ R_TILEGX_IMM8_Y0_TLS_GD_ADD = 115,+ R_TILEGX_IMM8_Y1_TLS_GD_ADD = 116,+ R_TILEGX_TLS_IE_LOAD = 117,+ R_TILEGX_IMM8_X0_TLS_ADD = 118,+ R_TILEGX_IMM8_X1_TLS_ADD = 119,+ R_TILEGX_IMM8_Y0_TLS_ADD = 120,+ R_TILEGX_IMM8_Y1_TLS_ADD = 121,+ R_TILEGX_GNU_VTINHERIT = 128,+ R_TILEGX_GNU_VTENTRY = 129,+ R_TILEGX_IRELATIVE = 130,+ R_TILEGX_NUM = 131+};++typedef enum+{+ TILEGX_PIPELINE_X0,+ TILEGX_PIPELINE_X1,+ TILEGX_PIPELINE_Y0,+ TILEGX_PIPELINE_Y1,+ TILEGX_PIPELINE_Y2,+} tilegx_pipeline;++typedef unsigned long long tilegx_bundle_bits;++/* These are the bits that determine if a bundle is in the X encoding. */+#define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62)++enum+{+ /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */+ TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3,++ /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */+ TILEGX_NUM_PIPELINE_ENCODINGS = 5,++ /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */+ TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3,++ /* Instructions take this many bytes. */+ TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES,++ /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */+ TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,++ /* Bundles should be aligned modulo this number of bytes. */+ TILEGX_BUNDLE_ALIGNMENT_IN_BYTES =+ (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),++ /* Number of registers (some are magic, such as network I/O). */+ TILEGX_NUM_REGISTERS = 64,+};++/* Make a few "tile_" variables to simplify common code between+ architectures. */++typedef tilegx_bundle_bits tile_bundle_bits;+#define TILE_BUNDLE_SIZE_IN_BYTES TILEGX_BUNDLE_SIZE_IN_BYTES+#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES+#define TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES \+ TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES++/* 64-bit pattern for a { bpt ; nop } bundle. */+#define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL++typedef enum+{+ TILEGX_OP_TYPE_REGISTER,+ TILEGX_OP_TYPE_IMMEDIATE,+ TILEGX_OP_TYPE_ADDRESS,+ TILEGX_OP_TYPE_SPR+} tilegx_operand_type;++struct tilegx_operand+{+ /* Is this operand a register, immediate or address? */+ tilegx_operand_type type;++ /* The default relocation type for this operand. */+ signed int default_reloc : 16;++ /* How many bits is this value? (used for range checking) */+ unsigned int num_bits : 5;++ /* Is the value signed? (used for range checking) */+ unsigned int is_signed : 1;++ /* Is this operand a source register? */+ unsigned int is_src_reg : 1;++ /* Is this operand written? (i.e. is it a destination register) */+ unsigned int is_dest_reg : 1;++ /* Is this operand PC-relative? */+ unsigned int is_pc_relative : 1;++ /* By how many bits do we right shift the value before inserting? */+ unsigned int rightshift : 2;++ /* Return the bits for this operand to be ORed into an existing bundle. */+ tilegx_bundle_bits (*insert) (int op);++ /* Extract this operand and return it. */+ unsigned int (*extract) (tilegx_bundle_bits bundle);+};++typedef enum+{+ TILEGX_OPC_BPT,+ TILEGX_OPC_INFO,+ TILEGX_OPC_INFOL,+ TILEGX_OPC_LD4S_TLS,+ TILEGX_OPC_LD_TLS,+ TILEGX_OPC_MOVE,+ TILEGX_OPC_MOVEI,+ TILEGX_OPC_MOVELI,+ TILEGX_OPC_PREFETCH,+ TILEGX_OPC_PREFETCH_ADD_L1,+ TILEGX_OPC_PREFETCH_ADD_L1_FAULT,+ TILEGX_OPC_PREFETCH_ADD_L2,+ TILEGX_OPC_PREFETCH_ADD_L2_FAULT,+ TILEGX_OPC_PREFETCH_ADD_L3,+ TILEGX_OPC_PREFETCH_ADD_L3_FAULT,+ TILEGX_OPC_PREFETCH_L1,+ TILEGX_OPC_PREFETCH_L1_FAULT,+ TILEGX_OPC_PREFETCH_L2,+ TILEGX_OPC_PREFETCH_L2_FAULT,+ TILEGX_OPC_PREFETCH_L3,+ TILEGX_OPC_PREFETCH_L3_FAULT,+ TILEGX_OPC_RAISE,+ TILEGX_OPC_ADD,+ TILEGX_OPC_ADDI,+ TILEGX_OPC_ADDLI,+ TILEGX_OPC_ADDX,+ TILEGX_OPC_ADDXI,+ TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXSC,+ TILEGX_OPC_AND,+ TILEGX_OPC_ANDI,+ TILEGX_OPC_BEQZ,+ TILEGX_OPC_BEQZT,+ TILEGX_OPC_BFEXTS,+ TILEGX_OPC_BFEXTU,+ TILEGX_OPC_BFINS,+ TILEGX_OPC_BGEZ,+ TILEGX_OPC_BGEZT,+ TILEGX_OPC_BGTZ,+ TILEGX_OPC_BGTZT,+ TILEGX_OPC_BLBC,+ TILEGX_OPC_BLBCT,+ TILEGX_OPC_BLBS,+ TILEGX_OPC_BLBST,+ TILEGX_OPC_BLEZ,+ TILEGX_OPC_BLEZT,+ TILEGX_OPC_BLTZ,+ TILEGX_OPC_BLTZT,+ TILEGX_OPC_BNEZ,+ TILEGX_OPC_BNEZT,+ TILEGX_OPC_CLZ,+ TILEGX_OPC_CMOVEQZ,+ TILEGX_OPC_CMOVNEZ,+ TILEGX_OPC_CMPEQ,+ TILEGX_OPC_CMPEQI,+ TILEGX_OPC_CMPEXCH,+ TILEGX_OPC_CMPEXCH4,+ TILEGX_OPC_CMPLES,+ TILEGX_OPC_CMPLEU,+ TILEGX_OPC_CMPLTS,+ TILEGX_OPC_CMPLTSI,+ TILEGX_OPC_CMPLTU,+ TILEGX_OPC_CMPLTUI,+ TILEGX_OPC_CMPNE,+ TILEGX_OPC_CMUL,+ TILEGX_OPC_CMULA,+ TILEGX_OPC_CMULAF,+ TILEGX_OPC_CMULF,+ TILEGX_OPC_CMULFR,+ TILEGX_OPC_CMULH,+ TILEGX_OPC_CMULHR,+ TILEGX_OPC_CRC32_32,+ TILEGX_OPC_CRC32_8,+ TILEGX_OPC_CTZ,+ TILEGX_OPC_DBLALIGN,+ TILEGX_OPC_DBLALIGN2,+ TILEGX_OPC_DBLALIGN4,+ TILEGX_OPC_DBLALIGN6,+ TILEGX_OPC_DRAIN,+ TILEGX_OPC_DTLBPR,+ TILEGX_OPC_EXCH,+ TILEGX_OPC_EXCH4,+ TILEGX_OPC_FDOUBLE_ADD_FLAGS,+ TILEGX_OPC_FDOUBLE_ADDSUB,+ TILEGX_OPC_FDOUBLE_MUL_FLAGS,+ TILEGX_OPC_FDOUBLE_PACK1,+ TILEGX_OPC_FDOUBLE_PACK2,+ TILEGX_OPC_FDOUBLE_SUB_FLAGS,+ TILEGX_OPC_FDOUBLE_UNPACK_MAX,+ TILEGX_OPC_FDOUBLE_UNPACK_MIN,+ TILEGX_OPC_FETCHADD,+ TILEGX_OPC_FETCHADD4,+ TILEGX_OPC_FETCHADDGEZ,+ TILEGX_OPC_FETCHADDGEZ4,+ TILEGX_OPC_FETCHAND,+ TILEGX_OPC_FETCHAND4,+ TILEGX_OPC_FETCHOR,+ TILEGX_OPC_FETCHOR4,+ TILEGX_OPC_FINV,+ TILEGX_OPC_FLUSH,+ TILEGX_OPC_FLUSHWB,+ TILEGX_OPC_FNOP,+ TILEGX_OPC_FSINGLE_ADD1,+ TILEGX_OPC_FSINGLE_ADDSUB2,+ TILEGX_OPC_FSINGLE_MUL1,+ TILEGX_OPC_FSINGLE_MUL2,+ TILEGX_OPC_FSINGLE_PACK1,+ TILEGX_OPC_FSINGLE_PACK2,+ TILEGX_OPC_FSINGLE_SUB1,+ TILEGX_OPC_ICOH,+ TILEGX_OPC_ILL,+ TILEGX_OPC_INV,+ TILEGX_OPC_IRET,+ TILEGX_OPC_J,+ TILEGX_OPC_JAL,+ TILEGX_OPC_JALR,+ TILEGX_OPC_JALRP,+ TILEGX_OPC_JR,+ TILEGX_OPC_JRP,+ TILEGX_OPC_LD,+ TILEGX_OPC_LD1S,+ TILEGX_OPC_LD1S_ADD,+ TILEGX_OPC_LD1U,+ TILEGX_OPC_LD1U_ADD,+ TILEGX_OPC_LD2S,+ TILEGX_OPC_LD2S_ADD,+ TILEGX_OPC_LD2U,+ TILEGX_OPC_LD2U_ADD,+ TILEGX_OPC_LD4S,+ TILEGX_OPC_LD4S_ADD,+ TILEGX_OPC_LD4U,+ TILEGX_OPC_LD4U_ADD,+ TILEGX_OPC_LD_ADD,+ TILEGX_OPC_LDNA,+ TILEGX_OPC_LDNA_ADD,+ TILEGX_OPC_LDNT,+ TILEGX_OPC_LDNT1S,+ TILEGX_OPC_LDNT1S_ADD,+ TILEGX_OPC_LDNT1U,+ TILEGX_OPC_LDNT1U_ADD,+ TILEGX_OPC_LDNT2S,+ TILEGX_OPC_LDNT2S_ADD,+ TILEGX_OPC_LDNT2U,+ TILEGX_OPC_LDNT2U_ADD,+ TILEGX_OPC_LDNT4S,+ TILEGX_OPC_LDNT4S_ADD,+ TILEGX_OPC_LDNT4U,+ TILEGX_OPC_LDNT4U_ADD,+ TILEGX_OPC_LDNT_ADD,+ TILEGX_OPC_LNK,+ TILEGX_OPC_MF,+ TILEGX_OPC_MFSPR,+ TILEGX_OPC_MM,+ TILEGX_OPC_MNZ,+ TILEGX_OPC_MTSPR,+ TILEGX_OPC_MUL_HS_HS,+ TILEGX_OPC_MUL_HS_HU,+ TILEGX_OPC_MUL_HS_LS,+ TILEGX_OPC_MUL_HS_LU,+ TILEGX_OPC_MUL_HU_HU,+ TILEGX_OPC_MUL_HU_LS,+ TILEGX_OPC_MUL_HU_LU,+ TILEGX_OPC_MUL_LS_LS,+ TILEGX_OPC_MUL_LS_LU,+ TILEGX_OPC_MUL_LU_LU,+ TILEGX_OPC_MULA_HS_HS,+ TILEGX_OPC_MULA_HS_HU,+ TILEGX_OPC_MULA_HS_LS,+ TILEGX_OPC_MULA_HS_LU,+ TILEGX_OPC_MULA_HU_HU,+ TILEGX_OPC_MULA_HU_LS,+ TILEGX_OPC_MULA_HU_LU,+ TILEGX_OPC_MULA_LS_LS,+ TILEGX_OPC_MULA_LS_LU,+ TILEGX_OPC_MULA_LU_LU,+ TILEGX_OPC_MULAX,+ TILEGX_OPC_MULX,+ TILEGX_OPC_MZ,+ TILEGX_OPC_NAP,+ TILEGX_OPC_NOP,+ TILEGX_OPC_NOR,+ TILEGX_OPC_OR,+ TILEGX_OPC_ORI,+ TILEGX_OPC_PCNT,+ TILEGX_OPC_REVBITS,+ TILEGX_OPC_REVBYTES,+ TILEGX_OPC_ROTL,+ TILEGX_OPC_ROTLI,+ TILEGX_OPC_SHL,+ TILEGX_OPC_SHL16INSLI,+ TILEGX_OPC_SHL1ADD,+ TILEGX_OPC_SHL1ADDX,+ TILEGX_OPC_SHL2ADD,+ TILEGX_OPC_SHL2ADDX,+ TILEGX_OPC_SHL3ADD,+ TILEGX_OPC_SHL3ADDX,+ TILEGX_OPC_SHLI,+ TILEGX_OPC_SHLX,+ TILEGX_OPC_SHLXI,+ TILEGX_OPC_SHRS,+ TILEGX_OPC_SHRSI,+ TILEGX_OPC_SHRU,+ TILEGX_OPC_SHRUI,+ TILEGX_OPC_SHRUX,+ TILEGX_OPC_SHRUXI,+ TILEGX_OPC_SHUFFLEBYTES,+ TILEGX_OPC_ST,+ TILEGX_OPC_ST1,+ TILEGX_OPC_ST1_ADD,+ TILEGX_OPC_ST2,+ TILEGX_OPC_ST2_ADD,+ TILEGX_OPC_ST4,+ TILEGX_OPC_ST4_ADD,+ TILEGX_OPC_ST_ADD,+ TILEGX_OPC_STNT,+ TILEGX_OPC_STNT1,+ TILEGX_OPC_STNT1_ADD,+ TILEGX_OPC_STNT2,+ TILEGX_OPC_STNT2_ADD,+ TILEGX_OPC_STNT4,+ TILEGX_OPC_STNT4_ADD,+ TILEGX_OPC_STNT_ADD,+ TILEGX_OPC_SUB,+ TILEGX_OPC_SUBX,+ TILEGX_OPC_SUBXSC,+ TILEGX_OPC_SWINT0,+ TILEGX_OPC_SWINT1,+ TILEGX_OPC_SWINT2,+ TILEGX_OPC_SWINT3,+ TILEGX_OPC_TBLIDXB0,+ TILEGX_OPC_TBLIDXB1,+ TILEGX_OPC_TBLIDXB2,+ TILEGX_OPC_TBLIDXB3,+ TILEGX_OPC_V1ADD,+ TILEGX_OPC_V1ADDI,+ TILEGX_OPC_V1ADDUC,+ TILEGX_OPC_V1ADIFFU,+ TILEGX_OPC_V1AVGU,+ TILEGX_OPC_V1CMPEQ,+ TILEGX_OPC_V1CMPEQI,+ TILEGX_OPC_V1CMPLES,+ TILEGX_OPC_V1CMPLEU,+ TILEGX_OPC_V1CMPLTS,+ TILEGX_OPC_V1CMPLTSI,+ TILEGX_OPC_V1CMPLTU,+ TILEGX_OPC_V1CMPLTUI,+ TILEGX_OPC_V1CMPNE,+ TILEGX_OPC_V1DDOTPU,+ TILEGX_OPC_V1DDOTPUA,+ TILEGX_OPC_V1DDOTPUS,+ TILEGX_OPC_V1DDOTPUSA,+ TILEGX_OPC_V1DOTP,+ TILEGX_OPC_V1DOTPA,+ TILEGX_OPC_V1DOTPU,+ TILEGX_OPC_V1DOTPUA,+ TILEGX_OPC_V1DOTPUS,+ TILEGX_OPC_V1DOTPUSA,+ TILEGX_OPC_V1INT_H,+ TILEGX_OPC_V1INT_L,+ TILEGX_OPC_V1MAXU,+ TILEGX_OPC_V1MAXUI,+ TILEGX_OPC_V1MINU,+ TILEGX_OPC_V1MINUI,+ TILEGX_OPC_V1MNZ,+ TILEGX_OPC_V1MULTU,+ TILEGX_OPC_V1MULU,+ TILEGX_OPC_V1MULUS,+ TILEGX_OPC_V1MZ,+ TILEGX_OPC_V1SADAU,+ TILEGX_OPC_V1SADU,+ TILEGX_OPC_V1SHL,+ TILEGX_OPC_V1SHLI,+ TILEGX_OPC_V1SHRS,+ TILEGX_OPC_V1SHRSI,+ TILEGX_OPC_V1SHRU,+ TILEGX_OPC_V1SHRUI,+ TILEGX_OPC_V1SUB,+ TILEGX_OPC_V1SUBUC,+ TILEGX_OPC_V2ADD,+ TILEGX_OPC_V2ADDI,+ TILEGX_OPC_V2ADDSC,+ TILEGX_OPC_V2ADIFFS,+ TILEGX_OPC_V2AVGS,+ TILEGX_OPC_V2CMPEQ,+ TILEGX_OPC_V2CMPEQI,+ TILEGX_OPC_V2CMPLES,+ TILEGX_OPC_V2CMPLEU,+ TILEGX_OPC_V2CMPLTS,+ TILEGX_OPC_V2CMPLTSI,+ TILEGX_OPC_V2CMPLTU,+ TILEGX_OPC_V2CMPLTUI,+ TILEGX_OPC_V2CMPNE,+ TILEGX_OPC_V2DOTP,+ TILEGX_OPC_V2DOTPA,+ TILEGX_OPC_V2INT_H,+ TILEGX_OPC_V2INT_L,+ TILEGX_OPC_V2MAXS,+ TILEGX_OPC_V2MAXSI,+ TILEGX_OPC_V2MINS,+ TILEGX_OPC_V2MINSI,+ TILEGX_OPC_V2MNZ,+ TILEGX_OPC_V2MULFSC,+ TILEGX_OPC_V2MULS,+ TILEGX_OPC_V2MULTS,+ TILEGX_OPC_V2MZ,+ TILEGX_OPC_V2PACKH,+ TILEGX_OPC_V2PACKL,+ TILEGX_OPC_V2PACKUC,+ TILEGX_OPC_V2SADAS,+ TILEGX_OPC_V2SADAU,+ TILEGX_OPC_V2SADS,+ TILEGX_OPC_V2SADU,+ TILEGX_OPC_V2SHL,+ TILEGX_OPC_V2SHLI,+ TILEGX_OPC_V2SHLSC,+ TILEGX_OPC_V2SHRS,+ TILEGX_OPC_V2SHRSI,+ TILEGX_OPC_V2SHRU,+ TILEGX_OPC_V2SHRUI,+ TILEGX_OPC_V2SUB,+ TILEGX_OPC_V2SUBSC,+ TILEGX_OPC_V4ADD,+ TILEGX_OPC_V4ADDSC,+ TILEGX_OPC_V4INT_H,+ TILEGX_OPC_V4INT_L,+ TILEGX_OPC_V4PACKSC,+ TILEGX_OPC_V4SHL,+ TILEGX_OPC_V4SHLSC,+ TILEGX_OPC_V4SHRS,+ TILEGX_OPC_V4SHRU,+ TILEGX_OPC_V4SUB,+ TILEGX_OPC_V4SUBSC,+ TILEGX_OPC_WH64,+ TILEGX_OPC_XOR,+ TILEGX_OPC_XORI,+ TILEGX_OPC_NONE+} tilegx_mnemonic;++enum+{+ TILEGX_MAX_OPERANDS = 4 /* bfexts */+};++struct tilegx_opcode+{+ /* The opcode mnemonic, e.g. "add" */+ const char *name;++ /* The enum value for this mnemonic. */+ tilegx_mnemonic mnemonic;++ /* A bit mask of which of the five pipes this instruction+ is compatible with:+ X0 0x01+ X1 0x02+ Y0 0x04+ Y1 0x08+ Y2 0x10 */+ unsigned char pipes;++ /* How many operands are there? */+ unsigned char num_operands;++ /* Which register does this write implicitly, or TREG_ZERO if none? */+ unsigned char implicitly_written_register;++ /* Can this be bundled with other instructions (almost always true). */+ unsigned char can_bundle;++ /* The description of the operands. Each of these is an+ * index into the tilegx_operands[] table. */+ unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS];++ /* A mask of which bits have predefined values for each pipeline.+ * This is useful for disassembly. */+ tilegx_bundle_bits fixed_bit_masks[TILEGX_NUM_PIPELINE_ENCODINGS];++ /* For each bit set in fixed_bit_masks, what the value is for this+ * instruction. */+ tilegx_bundle_bits fixed_bit_values[TILEGX_NUM_PIPELINE_ENCODINGS];+};++/* Used for non-textual disassembly into structs. */+struct tilegx_decoded_instruction+{+ const struct tilegx_opcode *opcode;+ const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS];+ long long operand_values[TILEGX_MAX_OPERANDS];+};++enum+{+ ADDI_IMM8_OPCODE_X0 = 1,+ ADDI_IMM8_OPCODE_X1 = 1,+ ADDI_OPCODE_Y0 = 0,+ ADDI_OPCODE_Y1 = 1,+ ADDLI_OPCODE_X0 = 1,+ ADDLI_OPCODE_X1 = 0,+ ADDXI_IMM8_OPCODE_X0 = 2,+ ADDXI_IMM8_OPCODE_X1 = 2,+ ADDXI_OPCODE_Y0 = 1,+ ADDXI_OPCODE_Y1 = 2,+ ADDXLI_OPCODE_X0 = 2,+ ADDXLI_OPCODE_X1 = 1,+ ADDXSC_RRR_0_OPCODE_X0 = 1,+ ADDXSC_RRR_0_OPCODE_X1 = 1,+ ADDX_RRR_0_OPCODE_X0 = 2,+ ADDX_RRR_0_OPCODE_X1 = 2,+ ADDX_RRR_0_OPCODE_Y0 = 0,+ ADDX_SPECIAL_0_OPCODE_Y1 = 0,+ ADD_RRR_0_OPCODE_X0 = 3,+ ADD_RRR_0_OPCODE_X1 = 3,+ ADD_RRR_0_OPCODE_Y0 = 1,+ ADD_SPECIAL_0_OPCODE_Y1 = 1,+ ANDI_IMM8_OPCODE_X0 = 3,+ ANDI_IMM8_OPCODE_X1 = 3,+ ANDI_OPCODE_Y0 = 2,+ ANDI_OPCODE_Y1 = 3,+ AND_RRR_0_OPCODE_X0 = 4,+ AND_RRR_0_OPCODE_X1 = 4,+ AND_RRR_5_OPCODE_Y0 = 0,+ AND_RRR_5_OPCODE_Y1 = 0,+ BEQZT_BRANCH_OPCODE_X1 = 16,+ BEQZ_BRANCH_OPCODE_X1 = 17,+ BFEXTS_BF_OPCODE_X0 = 4,+ BFEXTU_BF_OPCODE_X0 = 5,+ BFINS_BF_OPCODE_X0 = 6,+ BF_OPCODE_X0 = 3,+ BGEZT_BRANCH_OPCODE_X1 = 18,+ BGEZ_BRANCH_OPCODE_X1 = 19,+ BGTZT_BRANCH_OPCODE_X1 = 20,+ BGTZ_BRANCH_OPCODE_X1 = 21,+ BLBCT_BRANCH_OPCODE_X1 = 22,+ BLBC_BRANCH_OPCODE_X1 = 23,+ BLBST_BRANCH_OPCODE_X1 = 24,+ BLBS_BRANCH_OPCODE_X1 = 25,+ BLEZT_BRANCH_OPCODE_X1 = 26,+ BLEZ_BRANCH_OPCODE_X1 = 27,+ BLTZT_BRANCH_OPCODE_X1 = 28,+ BLTZ_BRANCH_OPCODE_X1 = 29,+ BNEZT_BRANCH_OPCODE_X1 = 30,+ BNEZ_BRANCH_OPCODE_X1 = 31,+ BRANCH_OPCODE_X1 = 2,+ CMOVEQZ_RRR_0_OPCODE_X0 = 5,+ CMOVEQZ_RRR_4_OPCODE_Y0 = 0,+ CMOVNEZ_RRR_0_OPCODE_X0 = 6,+ CMOVNEZ_RRR_4_OPCODE_Y0 = 1,+ CMPEQI_IMM8_OPCODE_X0 = 4,+ CMPEQI_IMM8_OPCODE_X1 = 4,+ CMPEQI_OPCODE_Y0 = 3,+ CMPEQI_OPCODE_Y1 = 4,+ CMPEQ_RRR_0_OPCODE_X0 = 7,+ CMPEQ_RRR_0_OPCODE_X1 = 5,+ CMPEQ_RRR_3_OPCODE_Y0 = 0,+ CMPEQ_RRR_3_OPCODE_Y1 = 2,+ CMPEXCH4_RRR_0_OPCODE_X1 = 6,+ CMPEXCH_RRR_0_OPCODE_X1 = 7,+ CMPLES_RRR_0_OPCODE_X0 = 8,+ CMPLES_RRR_0_OPCODE_X1 = 8,+ CMPLES_RRR_2_OPCODE_Y0 = 0,+ CMPLES_RRR_2_OPCODE_Y1 = 0,+ CMPLEU_RRR_0_OPCODE_X0 = 9,+ CMPLEU_RRR_0_OPCODE_X1 = 9,+ CMPLEU_RRR_2_OPCODE_Y0 = 1,+ CMPLEU_RRR_2_OPCODE_Y1 = 1,+ CMPLTSI_IMM8_OPCODE_X0 = 5,+ CMPLTSI_IMM8_OPCODE_X1 = 5,+ CMPLTSI_OPCODE_Y0 = 4,+ CMPLTSI_OPCODE_Y1 = 5,+ CMPLTS_RRR_0_OPCODE_X0 = 10,+ CMPLTS_RRR_0_OPCODE_X1 = 10,+ CMPLTS_RRR_2_OPCODE_Y0 = 2,+ CMPLTS_RRR_2_OPCODE_Y1 = 2,+ CMPLTUI_IMM8_OPCODE_X0 = 6,+ CMPLTUI_IMM8_OPCODE_X1 = 6,+ CMPLTU_RRR_0_OPCODE_X0 = 11,+ CMPLTU_RRR_0_OPCODE_X1 = 11,+ CMPLTU_RRR_2_OPCODE_Y0 = 3,+ CMPLTU_RRR_2_OPCODE_Y1 = 3,+ CMPNE_RRR_0_OPCODE_X0 = 12,+ CMPNE_RRR_0_OPCODE_X1 = 12,+ CMPNE_RRR_3_OPCODE_Y0 = 1,+ CMPNE_RRR_3_OPCODE_Y1 = 3,+ CMULAF_RRR_0_OPCODE_X0 = 13,+ CMULA_RRR_0_OPCODE_X0 = 14,+ CMULFR_RRR_0_OPCODE_X0 = 15,+ CMULF_RRR_0_OPCODE_X0 = 16,+ CMULHR_RRR_0_OPCODE_X0 = 17,+ CMULH_RRR_0_OPCODE_X0 = 18,+ CMUL_RRR_0_OPCODE_X0 = 19,+ CNTLZ_UNARY_OPCODE_X0 = 1,+ CNTLZ_UNARY_OPCODE_Y0 = 1,+ CNTTZ_UNARY_OPCODE_X0 = 2,+ CNTTZ_UNARY_OPCODE_Y0 = 2,+ CRC32_32_RRR_0_OPCODE_X0 = 20,+ CRC32_8_RRR_0_OPCODE_X0 = 21,+ DBLALIGN2_RRR_0_OPCODE_X0 = 22,+ DBLALIGN2_RRR_0_OPCODE_X1 = 13,+ DBLALIGN4_RRR_0_OPCODE_X0 = 23,+ DBLALIGN4_RRR_0_OPCODE_X1 = 14,+ DBLALIGN6_RRR_0_OPCODE_X0 = 24,+ DBLALIGN6_RRR_0_OPCODE_X1 = 15,+ DBLALIGN_RRR_0_OPCODE_X0 = 25,+ DRAIN_UNARY_OPCODE_X1 = 1,+ DTLBPR_UNARY_OPCODE_X1 = 2,+ EXCH4_RRR_0_OPCODE_X1 = 16,+ EXCH_RRR_0_OPCODE_X1 = 17,+ FDOUBLE_ADDSUB_RRR_0_OPCODE_X0 = 26,+ FDOUBLE_ADD_FLAGS_RRR_0_OPCODE_X0 = 27,+ FDOUBLE_MUL_FLAGS_RRR_0_OPCODE_X0 = 28,+ FDOUBLE_PACK1_RRR_0_OPCODE_X0 = 29,+ FDOUBLE_PACK2_RRR_0_OPCODE_X0 = 30,+ FDOUBLE_SUB_FLAGS_RRR_0_OPCODE_X0 = 31,+ FDOUBLE_UNPACK_MAX_RRR_0_OPCODE_X0 = 32,+ FDOUBLE_UNPACK_MIN_RRR_0_OPCODE_X0 = 33,+ FETCHADD4_RRR_0_OPCODE_X1 = 18,+ FETCHADDGEZ4_RRR_0_OPCODE_X1 = 19,+ FETCHADDGEZ_RRR_0_OPCODE_X1 = 20,+ FETCHADD_RRR_0_OPCODE_X1 = 21,+ FETCHAND4_RRR_0_OPCODE_X1 = 22,+ FETCHAND_RRR_0_OPCODE_X1 = 23,+ FETCHOR4_RRR_0_OPCODE_X1 = 24,+ FETCHOR_RRR_0_OPCODE_X1 = 25,+ FINV_UNARY_OPCODE_X1 = 3,+ FLUSHWB_UNARY_OPCODE_X1 = 4,+ FLUSH_UNARY_OPCODE_X1 = 5,+ FNOP_UNARY_OPCODE_X0 = 3,+ FNOP_UNARY_OPCODE_X1 = 6,+ FNOP_UNARY_OPCODE_Y0 = 3,+ FNOP_UNARY_OPCODE_Y1 = 8,+ FSINGLE_ADD1_RRR_0_OPCODE_X0 = 34,+ FSINGLE_ADDSUB2_RRR_0_OPCODE_X0 = 35,+ FSINGLE_MUL1_RRR_0_OPCODE_X0 = 36,+ FSINGLE_MUL2_RRR_0_OPCODE_X0 = 37,+ FSINGLE_PACK1_UNARY_OPCODE_X0 = 4,+ FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4,+ FSINGLE_PACK2_RRR_0_OPCODE_X0 = 38,+ FSINGLE_SUB1_RRR_0_OPCODE_X0 = 39,+ ICOH_UNARY_OPCODE_X1 = 7,+ ILL_UNARY_OPCODE_X1 = 8,+ ILL_UNARY_OPCODE_Y1 = 9,+ IMM8_OPCODE_X0 = 4,+ IMM8_OPCODE_X1 = 3,+ INV_UNARY_OPCODE_X1 = 9,+ IRET_UNARY_OPCODE_X1 = 10,+ JALRP_UNARY_OPCODE_X1 = 11,+ JALRP_UNARY_OPCODE_Y1 = 10,+ JALR_UNARY_OPCODE_X1 = 12,+ JALR_UNARY_OPCODE_Y1 = 11,+ JAL_JUMP_OPCODE_X1 = 0,+ JRP_UNARY_OPCODE_X1 = 13,+ JRP_UNARY_OPCODE_Y1 = 12,+ JR_UNARY_OPCODE_X1 = 14,+ JR_UNARY_OPCODE_Y1 = 13,+ JUMP_OPCODE_X1 = 4,+ J_JUMP_OPCODE_X1 = 1,+ LD1S_ADD_IMM8_OPCODE_X1 = 7,+ LD1S_OPCODE_Y2 = 0,+ LD1S_UNARY_OPCODE_X1 = 15,+ LD1U_ADD_IMM8_OPCODE_X1 = 8,+ LD1U_OPCODE_Y2 = 1,+ LD1U_UNARY_OPCODE_X1 = 16,+ LD2S_ADD_IMM8_OPCODE_X1 = 9,+ LD2S_OPCODE_Y2 = 2,+ LD2S_UNARY_OPCODE_X1 = 17,+ LD2U_ADD_IMM8_OPCODE_X1 = 10,+ LD2U_OPCODE_Y2 = 3,+ LD2U_UNARY_OPCODE_X1 = 18,+ LD4S_ADD_IMM8_OPCODE_X1 = 11,+ LD4S_OPCODE_Y2 = 1,+ LD4S_UNARY_OPCODE_X1 = 19,+ LD4U_ADD_IMM8_OPCODE_X1 = 12,+ LD4U_OPCODE_Y2 = 2,+ LD4U_UNARY_OPCODE_X1 = 20,+ LDNA_UNARY_OPCODE_X1 = 21,+ LDNT1S_ADD_IMM8_OPCODE_X1 = 13,+ LDNT1S_UNARY_OPCODE_X1 = 22,+ LDNT1U_ADD_IMM8_OPCODE_X1 = 14,+ LDNT1U_UNARY_OPCODE_X1 = 23,+ LDNT2S_ADD_IMM8_OPCODE_X1 = 15,+ LDNT2S_UNARY_OPCODE_X1 = 24,+ LDNT2U_ADD_IMM8_OPCODE_X1 = 16,+ LDNT2U_UNARY_OPCODE_X1 = 25,+ LDNT4S_ADD_IMM8_OPCODE_X1 = 17,+ LDNT4S_UNARY_OPCODE_X1 = 26,+ LDNT4U_ADD_IMM8_OPCODE_X1 = 18,+ LDNT4U_UNARY_OPCODE_X1 = 27,+ LDNT_ADD_IMM8_OPCODE_X1 = 19,+ LDNT_UNARY_OPCODE_X1 = 28,+ LD_ADD_IMM8_OPCODE_X1 = 20,+ LD_OPCODE_Y2 = 3,+ LD_UNARY_OPCODE_X1 = 29,+ LNK_UNARY_OPCODE_X1 = 30,+ LNK_UNARY_OPCODE_Y1 = 14,+ LWNA_ADD_IMM8_OPCODE_X1 = 21,+ MFSPR_IMM8_OPCODE_X1 = 22,+ MF_UNARY_OPCODE_X1 = 31,+ MM_BF_OPCODE_X0 = 7,+ MNZ_RRR_0_OPCODE_X0 = 40,+ MNZ_RRR_0_OPCODE_X1 = 26,+ MNZ_RRR_4_OPCODE_Y0 = 2,+ MNZ_RRR_4_OPCODE_Y1 = 2,+ MODE_OPCODE_YA2 = 1,+ MODE_OPCODE_YB2 = 2,+ MODE_OPCODE_YC2 = 3,+ MTSPR_IMM8_OPCODE_X1 = 23,+ MULAX_RRR_0_OPCODE_X0 = 41,+ MULAX_RRR_3_OPCODE_Y0 = 2,+ MULA_HS_HS_RRR_0_OPCODE_X0 = 42,+ MULA_HS_HS_RRR_9_OPCODE_Y0 = 0,+ MULA_HS_HU_RRR_0_OPCODE_X0 = 43,+ MULA_HS_LS_RRR_0_OPCODE_X0 = 44,+ MULA_HS_LU_RRR_0_OPCODE_X0 = 45,+ MULA_HU_HU_RRR_0_OPCODE_X0 = 46,+ MULA_HU_HU_RRR_9_OPCODE_Y0 = 1,+ MULA_HU_LS_RRR_0_OPCODE_X0 = 47,+ MULA_HU_LU_RRR_0_OPCODE_X0 = 48,+ MULA_LS_LS_RRR_0_OPCODE_X0 = 49,+ MULA_LS_LS_RRR_9_OPCODE_Y0 = 2,+ MULA_LS_LU_RRR_0_OPCODE_X0 = 50,+ MULA_LU_LU_RRR_0_OPCODE_X0 = 51,+ MULA_LU_LU_RRR_9_OPCODE_Y0 = 3,+ MULX_RRR_0_OPCODE_X0 = 52,+ MULX_RRR_3_OPCODE_Y0 = 3,+ MUL_HS_HS_RRR_0_OPCODE_X0 = 53,+ MUL_HS_HS_RRR_8_OPCODE_Y0 = 0,+ MUL_HS_HU_RRR_0_OPCODE_X0 = 54,+ MUL_HS_LS_RRR_0_OPCODE_X0 = 55,+ MUL_HS_LU_RRR_0_OPCODE_X0 = 56,+ MUL_HU_HU_RRR_0_OPCODE_X0 = 57,+ MUL_HU_HU_RRR_8_OPCODE_Y0 = 1,+ MUL_HU_LS_RRR_0_OPCODE_X0 = 58,+ MUL_HU_LU_RRR_0_OPCODE_X0 = 59,+ MUL_LS_LS_RRR_0_OPCODE_X0 = 60,+ MUL_LS_LS_RRR_8_OPCODE_Y0 = 2,+ MUL_LS_LU_RRR_0_OPCODE_X0 = 61,+ MUL_LU_LU_RRR_0_OPCODE_X0 = 62,+ MUL_LU_LU_RRR_8_OPCODE_Y0 = 3,+ MZ_RRR_0_OPCODE_X0 = 63,+ MZ_RRR_0_OPCODE_X1 = 27,+ MZ_RRR_4_OPCODE_Y0 = 3,+ MZ_RRR_4_OPCODE_Y1 = 3,+ NAP_UNARY_OPCODE_X1 = 32,+ NOP_UNARY_OPCODE_X0 = 5,+ NOP_UNARY_OPCODE_X1 = 33,+ NOP_UNARY_OPCODE_Y0 = 5,+ NOP_UNARY_OPCODE_Y1 = 15,+ NOR_RRR_0_OPCODE_X0 = 64,+ NOR_RRR_0_OPCODE_X1 = 28,+ NOR_RRR_5_OPCODE_Y0 = 1,+ NOR_RRR_5_OPCODE_Y1 = 1,+ ORI_IMM8_OPCODE_X0 = 7,+ ORI_IMM8_OPCODE_X1 = 24,+ OR_RRR_0_OPCODE_X0 = 65,+ OR_RRR_0_OPCODE_X1 = 29,+ OR_RRR_5_OPCODE_Y0 = 2,+ OR_RRR_5_OPCODE_Y1 = 2,+ PCNT_UNARY_OPCODE_X0 = 6,+ PCNT_UNARY_OPCODE_Y0 = 6,+ REVBITS_UNARY_OPCODE_X0 = 7,+ REVBITS_UNARY_OPCODE_Y0 = 7,+ REVBYTES_UNARY_OPCODE_X0 = 8,+ REVBYTES_UNARY_OPCODE_Y0 = 8,+ ROTLI_SHIFT_OPCODE_X0 = 1,+ ROTLI_SHIFT_OPCODE_X1 = 1,+ ROTLI_SHIFT_OPCODE_Y0 = 0,+ ROTLI_SHIFT_OPCODE_Y1 = 0,+ ROTL_RRR_0_OPCODE_X0 = 66,+ ROTL_RRR_0_OPCODE_X1 = 30,+ ROTL_RRR_6_OPCODE_Y0 = 0,+ ROTL_RRR_6_OPCODE_Y1 = 0,+ RRR_0_OPCODE_X0 = 5,+ RRR_0_OPCODE_X1 = 5,+ RRR_0_OPCODE_Y0 = 5,+ RRR_0_OPCODE_Y1 = 6,+ RRR_1_OPCODE_Y0 = 6,+ RRR_1_OPCODE_Y1 = 7,+ RRR_2_OPCODE_Y0 = 7,+ RRR_2_OPCODE_Y1 = 8,+ RRR_3_OPCODE_Y0 = 8,+ RRR_3_OPCODE_Y1 = 9,+ RRR_4_OPCODE_Y0 = 9,+ RRR_4_OPCODE_Y1 = 10,+ RRR_5_OPCODE_Y0 = 10,+ RRR_5_OPCODE_Y1 = 11,+ RRR_6_OPCODE_Y0 = 11,+ RRR_6_OPCODE_Y1 = 12,+ RRR_7_OPCODE_Y0 = 12,+ RRR_7_OPCODE_Y1 = 13,+ RRR_8_OPCODE_Y0 = 13,+ RRR_9_OPCODE_Y0 = 14,+ SHIFT_OPCODE_X0 = 6,+ SHIFT_OPCODE_X1 = 6,+ SHIFT_OPCODE_Y0 = 15,+ SHIFT_OPCODE_Y1 = 14,+ SHL16INSLI_OPCODE_X0 = 7,+ SHL16INSLI_OPCODE_X1 = 7,+ SHL1ADDX_RRR_0_OPCODE_X0 = 67,+ SHL1ADDX_RRR_0_OPCODE_X1 = 31,+ SHL1ADDX_RRR_7_OPCODE_Y0 = 1,+ SHL1ADDX_RRR_7_OPCODE_Y1 = 1,+ SHL1ADD_RRR_0_OPCODE_X0 = 68,+ SHL1ADD_RRR_0_OPCODE_X1 = 32,+ SHL1ADD_RRR_1_OPCODE_Y0 = 0,+ SHL1ADD_RRR_1_OPCODE_Y1 = 0,+ SHL2ADDX_RRR_0_OPCODE_X0 = 69,+ SHL2ADDX_RRR_0_OPCODE_X1 = 33,+ SHL2ADDX_RRR_7_OPCODE_Y0 = 2,+ SHL2ADDX_RRR_7_OPCODE_Y1 = 2,+ SHL2ADD_RRR_0_OPCODE_X0 = 70,+ SHL2ADD_RRR_0_OPCODE_X1 = 34,+ SHL2ADD_RRR_1_OPCODE_Y0 = 1,+ SHL2ADD_RRR_1_OPCODE_Y1 = 1,+ SHL3ADDX_RRR_0_OPCODE_X0 = 71,+ SHL3ADDX_RRR_0_OPCODE_X1 = 35,+ SHL3ADDX_RRR_7_OPCODE_Y0 = 3,+ SHL3ADDX_RRR_7_OPCODE_Y1 = 3,+ SHL3ADD_RRR_0_OPCODE_X0 = 72,+ SHL3ADD_RRR_0_OPCODE_X1 = 36,+ SHL3ADD_RRR_1_OPCODE_Y0 = 2,+ SHL3ADD_RRR_1_OPCODE_Y1 = 2,+ SHLI_SHIFT_OPCODE_X0 = 2,+ SHLI_SHIFT_OPCODE_X1 = 2,+ SHLI_SHIFT_OPCODE_Y0 = 1,+ SHLI_SHIFT_OPCODE_Y1 = 1,+ SHLXI_SHIFT_OPCODE_X0 = 3,+ SHLXI_SHIFT_OPCODE_X1 = 3,+ SHLX_RRR_0_OPCODE_X0 = 73,+ SHLX_RRR_0_OPCODE_X1 = 37,+ SHL_RRR_0_OPCODE_X0 = 74,+ SHL_RRR_0_OPCODE_X1 = 38,+ SHL_RRR_6_OPCODE_Y0 = 1,+ SHL_RRR_6_OPCODE_Y1 = 1,+ SHRSI_SHIFT_OPCODE_X0 = 4,+ SHRSI_SHIFT_OPCODE_X1 = 4,+ SHRSI_SHIFT_OPCODE_Y0 = 2,+ SHRSI_SHIFT_OPCODE_Y1 = 2,+ SHRS_RRR_0_OPCODE_X0 = 75,+ SHRS_RRR_0_OPCODE_X1 = 39,+ SHRS_RRR_6_OPCODE_Y0 = 2,+ SHRS_RRR_6_OPCODE_Y1 = 2,+ SHRUI_SHIFT_OPCODE_X0 = 5,+ SHRUI_SHIFT_OPCODE_X1 = 5,+ SHRUI_SHIFT_OPCODE_Y0 = 3,+ SHRUI_SHIFT_OPCODE_Y1 = 3,+ SHRUXI_SHIFT_OPCODE_X0 = 6,+ SHRUXI_SHIFT_OPCODE_X1 = 6,+ SHRUX_RRR_0_OPCODE_X0 = 76,+ SHRUX_RRR_0_OPCODE_X1 = 40,+ SHRU_RRR_0_OPCODE_X0 = 77,+ SHRU_RRR_0_OPCODE_X1 = 41,+ SHRU_RRR_6_OPCODE_Y0 = 3,+ SHRU_RRR_6_OPCODE_Y1 = 3,+ SHUFFLEBYTES_RRR_0_OPCODE_X0 = 78,+ ST1_ADD_IMM8_OPCODE_X1 = 25,+ ST1_OPCODE_Y2 = 0,+ ST1_RRR_0_OPCODE_X1 = 42,+ ST2_ADD_IMM8_OPCODE_X1 = 26,+ ST2_OPCODE_Y2 = 1,+ ST2_RRR_0_OPCODE_X1 = 43,+ ST4_ADD_IMM8_OPCODE_X1 = 27,+ ST4_OPCODE_Y2 = 2,+ ST4_RRR_0_OPCODE_X1 = 44,+ STNT1_ADD_IMM8_OPCODE_X1 = 28,+ STNT1_RRR_0_OPCODE_X1 = 45,+ STNT2_ADD_IMM8_OPCODE_X1 = 29,+ STNT2_RRR_0_OPCODE_X1 = 46,+ STNT4_ADD_IMM8_OPCODE_X1 = 30,+ STNT4_RRR_0_OPCODE_X1 = 47,+ STNT_ADD_IMM8_OPCODE_X1 = 31,+ STNT_RRR_0_OPCODE_X1 = 48,+ ST_ADD_IMM8_OPCODE_X1 = 32,+ ST_OPCODE_Y2 = 3,+ ST_RRR_0_OPCODE_X1 = 49,+ SUBXSC_RRR_0_OPCODE_X0 = 79,+ SUBXSC_RRR_0_OPCODE_X1 = 50,+ SUBX_RRR_0_OPCODE_X0 = 80,+ SUBX_RRR_0_OPCODE_X1 = 51,+ SUBX_RRR_0_OPCODE_Y0 = 2,+ SUBX_RRR_0_OPCODE_Y1 = 2,+ SUB_RRR_0_OPCODE_X0 = 81,+ SUB_RRR_0_OPCODE_X1 = 52,+ SUB_RRR_0_OPCODE_Y0 = 3,+ SUB_RRR_0_OPCODE_Y1 = 3,+ SWINT0_UNARY_OPCODE_X1 = 34,+ SWINT1_UNARY_OPCODE_X1 = 35,+ SWINT2_UNARY_OPCODE_X1 = 36,+ SWINT3_UNARY_OPCODE_X1 = 37,+ TBLIDXB0_UNARY_OPCODE_X0 = 9,+ TBLIDXB0_UNARY_OPCODE_Y0 = 9,+ TBLIDXB1_UNARY_OPCODE_X0 = 10,+ TBLIDXB1_UNARY_OPCODE_Y0 = 10,+ TBLIDXB2_UNARY_OPCODE_X0 = 11,+ TBLIDXB2_UNARY_OPCODE_Y0 = 11,+ TBLIDXB3_UNARY_OPCODE_X0 = 12,+ TBLIDXB3_UNARY_OPCODE_Y0 = 12,+ UNARY_RRR_0_OPCODE_X0 = 82,+ UNARY_RRR_0_OPCODE_X1 = 53,+ UNARY_RRR_1_OPCODE_Y0 = 3,+ UNARY_RRR_1_OPCODE_Y1 = 3,+ V1ADDI_IMM8_OPCODE_X0 = 8,+ V1ADDI_IMM8_OPCODE_X1 = 33,+ V1ADDUC_RRR_0_OPCODE_X0 = 83,+ V1ADDUC_RRR_0_OPCODE_X1 = 54,+ V1ADD_RRR_0_OPCODE_X0 = 84,+ V1ADD_RRR_0_OPCODE_X1 = 55,+ V1ADIFFU_RRR_0_OPCODE_X0 = 85,+ V1AVGU_RRR_0_OPCODE_X0 = 86,+ V1CMPEQI_IMM8_OPCODE_X0 = 9,+ V1CMPEQI_IMM8_OPCODE_X1 = 34,+ V1CMPEQ_RRR_0_OPCODE_X0 = 87,+ V1CMPEQ_RRR_0_OPCODE_X1 = 56,+ V1CMPLES_RRR_0_OPCODE_X0 = 88,+ V1CMPLES_RRR_0_OPCODE_X1 = 57,+ V1CMPLEU_RRR_0_OPCODE_X0 = 89,+ V1CMPLEU_RRR_0_OPCODE_X1 = 58,+ V1CMPLTSI_IMM8_OPCODE_X0 = 10,+ V1CMPLTSI_IMM8_OPCODE_X1 = 35,+ V1CMPLTS_RRR_0_OPCODE_X0 = 90,+ V1CMPLTS_RRR_0_OPCODE_X1 = 59,+ V1CMPLTUI_IMM8_OPCODE_X0 = 11,+ V1CMPLTUI_IMM8_OPCODE_X1 = 36,+ V1CMPLTU_RRR_0_OPCODE_X0 = 91,+ V1CMPLTU_RRR_0_OPCODE_X1 = 60,+ V1CMPNE_RRR_0_OPCODE_X0 = 92,+ V1CMPNE_RRR_0_OPCODE_X1 = 61,+ V1DDOTPUA_RRR_0_OPCODE_X0 = 161,+ V1DDOTPUSA_RRR_0_OPCODE_X0 = 93,+ V1DDOTPUS_RRR_0_OPCODE_X0 = 94,+ V1DDOTPU_RRR_0_OPCODE_X0 = 162,+ V1DOTPA_RRR_0_OPCODE_X0 = 95,+ V1DOTPUA_RRR_0_OPCODE_X0 = 163,+ V1DOTPUSA_RRR_0_OPCODE_X0 = 96,+ V1DOTPUS_RRR_0_OPCODE_X0 = 97,+ V1DOTPU_RRR_0_OPCODE_X0 = 164,+ V1DOTP_RRR_0_OPCODE_X0 = 98,+ V1INT_H_RRR_0_OPCODE_X0 = 99,+ V1INT_H_RRR_0_OPCODE_X1 = 62,+ V1INT_L_RRR_0_OPCODE_X0 = 100,+ V1INT_L_RRR_0_OPCODE_X1 = 63,+ V1MAXUI_IMM8_OPCODE_X0 = 12,+ V1MAXUI_IMM8_OPCODE_X1 = 37,+ V1MAXU_RRR_0_OPCODE_X0 = 101,+ V1MAXU_RRR_0_OPCODE_X1 = 64,+ V1MINUI_IMM8_OPCODE_X0 = 13,+ V1MINUI_IMM8_OPCODE_X1 = 38,+ V1MINU_RRR_0_OPCODE_X0 = 102,+ V1MINU_RRR_0_OPCODE_X1 = 65,+ V1MNZ_RRR_0_OPCODE_X0 = 103,+ V1MNZ_RRR_0_OPCODE_X1 = 66,+ V1MULTU_RRR_0_OPCODE_X0 = 104,+ V1MULUS_RRR_0_OPCODE_X0 = 105,+ V1MULU_RRR_0_OPCODE_X0 = 106,+ V1MZ_RRR_0_OPCODE_X0 = 107,+ V1MZ_RRR_0_OPCODE_X1 = 67,+ V1SADAU_RRR_0_OPCODE_X0 = 108,+ V1SADU_RRR_0_OPCODE_X0 = 109,+ V1SHLI_SHIFT_OPCODE_X0 = 7,+ V1SHLI_SHIFT_OPCODE_X1 = 7,+ V1SHL_RRR_0_OPCODE_X0 = 110,+ V1SHL_RRR_0_OPCODE_X1 = 68,+ V1SHRSI_SHIFT_OPCODE_X0 = 8,+ V1SHRSI_SHIFT_OPCODE_X1 = 8,+ V1SHRS_RRR_0_OPCODE_X0 = 111,+ V1SHRS_RRR_0_OPCODE_X1 = 69,+ V1SHRUI_SHIFT_OPCODE_X0 = 9,+ V1SHRUI_SHIFT_OPCODE_X1 = 9,+ V1SHRU_RRR_0_OPCODE_X0 = 112,+ V1SHRU_RRR_0_OPCODE_X1 = 70,+ V1SUBUC_RRR_0_OPCODE_X0 = 113,+ V1SUBUC_RRR_0_OPCODE_X1 = 71,+ V1SUB_RRR_0_OPCODE_X0 = 114,+ V1SUB_RRR_0_OPCODE_X1 = 72,+ V2ADDI_IMM8_OPCODE_X0 = 14,+ V2ADDI_IMM8_OPCODE_X1 = 39,+ V2ADDSC_RRR_0_OPCODE_X0 = 115,+ V2ADDSC_RRR_0_OPCODE_X1 = 73,+ V2ADD_RRR_0_OPCODE_X0 = 116,+ V2ADD_RRR_0_OPCODE_X1 = 74,+ V2ADIFFS_RRR_0_OPCODE_X0 = 117,+ V2AVGS_RRR_0_OPCODE_X0 = 118,+ V2CMPEQI_IMM8_OPCODE_X0 = 15,+ V2CMPEQI_IMM8_OPCODE_X1 = 40,+ V2CMPEQ_RRR_0_OPCODE_X0 = 119,+ V2CMPEQ_RRR_0_OPCODE_X1 = 75,+ V2CMPLES_RRR_0_OPCODE_X0 = 120,+ V2CMPLES_RRR_0_OPCODE_X1 = 76,+ V2CMPLEU_RRR_0_OPCODE_X0 = 121,+ V2CMPLEU_RRR_0_OPCODE_X1 = 77,+ V2CMPLTSI_IMM8_OPCODE_X0 = 16,+ V2CMPLTSI_IMM8_OPCODE_X1 = 41,+ V2CMPLTS_RRR_0_OPCODE_X0 = 122,+ V2CMPLTS_RRR_0_OPCODE_X1 = 78,+ V2CMPLTUI_IMM8_OPCODE_X0 = 17,+ V2CMPLTUI_IMM8_OPCODE_X1 = 42,+ V2CMPLTU_RRR_0_OPCODE_X0 = 123,+ V2CMPLTU_RRR_0_OPCODE_X1 = 79,+ V2CMPNE_RRR_0_OPCODE_X0 = 124,+ V2CMPNE_RRR_0_OPCODE_X1 = 80,+ V2DOTPA_RRR_0_OPCODE_X0 = 125,+ V2DOTP_RRR_0_OPCODE_X0 = 126,+ V2INT_H_RRR_0_OPCODE_X0 = 127,+ V2INT_H_RRR_0_OPCODE_X1 = 81,+ V2INT_L_RRR_0_OPCODE_X0 = 128,+ V2INT_L_RRR_0_OPCODE_X1 = 82,+ V2MAXSI_IMM8_OPCODE_X0 = 18,+ V2MAXSI_IMM8_OPCODE_X1 = 43,+ V2MAXS_RRR_0_OPCODE_X0 = 129,+ V2MAXS_RRR_0_OPCODE_X1 = 83,+ V2MINSI_IMM8_OPCODE_X0 = 19,+ V2MINSI_IMM8_OPCODE_X1 = 44,+ V2MINS_RRR_0_OPCODE_X0 = 130,+ V2MINS_RRR_0_OPCODE_X1 = 84,+ V2MNZ_RRR_0_OPCODE_X0 = 131,+ V2MNZ_RRR_0_OPCODE_X1 = 85,+ V2MULFSC_RRR_0_OPCODE_X0 = 132,+ V2MULS_RRR_0_OPCODE_X0 = 133,+ V2MULTS_RRR_0_OPCODE_X0 = 134,+ V2MZ_RRR_0_OPCODE_X0 = 135,+ V2MZ_RRR_0_OPCODE_X1 = 86,+ V2PACKH_RRR_0_OPCODE_X0 = 136,+ V2PACKH_RRR_0_OPCODE_X1 = 87,+ V2PACKL_RRR_0_OPCODE_X0 = 137,+ V2PACKL_RRR_0_OPCODE_X1 = 88,+ V2PACKUC_RRR_0_OPCODE_X0 = 138,+ V2PACKUC_RRR_0_OPCODE_X1 = 89,+ V2SADAS_RRR_0_OPCODE_X0 = 139,+ V2SADAU_RRR_0_OPCODE_X0 = 140,+ V2SADS_RRR_0_OPCODE_X0 = 141,+ V2SADU_RRR_0_OPCODE_X0 = 142,+ V2SHLI_SHIFT_OPCODE_X0 = 10,+ V2SHLI_SHIFT_OPCODE_X1 = 10,+ V2SHLSC_RRR_0_OPCODE_X0 = 143,+ V2SHLSC_RRR_0_OPCODE_X1 = 90,+ V2SHL_RRR_0_OPCODE_X0 = 144,+ V2SHL_RRR_0_OPCODE_X1 = 91,+ V2SHRSI_SHIFT_OPCODE_X0 = 11,+ V2SHRSI_SHIFT_OPCODE_X1 = 11,+ V2SHRS_RRR_0_OPCODE_X0 = 145,+ V2SHRS_RRR_0_OPCODE_X1 = 92,+ V2SHRUI_SHIFT_OPCODE_X0 = 12,+ V2SHRUI_SHIFT_OPCODE_X1 = 12,+ V2SHRU_RRR_0_OPCODE_X0 = 146,+ V2SHRU_RRR_0_OPCODE_X1 = 93,+ V2SUBSC_RRR_0_OPCODE_X0 = 147,+ V2SUBSC_RRR_0_OPCODE_X1 = 94,+ V2SUB_RRR_0_OPCODE_X0 = 148,+ V2SUB_RRR_0_OPCODE_X1 = 95,+ V4ADDSC_RRR_0_OPCODE_X0 = 149,+ V4ADDSC_RRR_0_OPCODE_X1 = 96,+ V4ADD_RRR_0_OPCODE_X0 = 150,+ V4ADD_RRR_0_OPCODE_X1 = 97,+ V4INT_H_RRR_0_OPCODE_X0 = 151,+ V4INT_H_RRR_0_OPCODE_X1 = 98,+ V4INT_L_RRR_0_OPCODE_X0 = 152,+ V4INT_L_RRR_0_OPCODE_X1 = 99,+ V4PACKSC_RRR_0_OPCODE_X0 = 153,+ V4PACKSC_RRR_0_OPCODE_X1 = 100,+ V4SHLSC_RRR_0_OPCODE_X0 = 154,+ V4SHLSC_RRR_0_OPCODE_X1 = 101,+ V4SHL_RRR_0_OPCODE_X0 = 155,+ V4SHL_RRR_0_OPCODE_X1 = 102,+ V4SHRS_RRR_0_OPCODE_X0 = 156,+ V4SHRS_RRR_0_OPCODE_X1 = 103,+ V4SHRU_RRR_0_OPCODE_X0 = 157,+ V4SHRU_RRR_0_OPCODE_X1 = 104,+ V4SUBSC_RRR_0_OPCODE_X0 = 158,+ V4SUBSC_RRR_0_OPCODE_X1 = 105,+ V4SUB_RRR_0_OPCODE_X0 = 159,+ V4SUB_RRR_0_OPCODE_X1 = 106,+ WH64_UNARY_OPCODE_X1 = 38,+ XORI_IMM8_OPCODE_X0 = 20,+ XORI_IMM8_OPCODE_X1 = 45,+ XOR_RRR_0_OPCODE_X0 = 160,+ XOR_RRR_0_OPCODE_X1 = 107,+ XOR_RRR_5_OPCODE_Y0 = 3,+ XOR_RRR_5_OPCODE_Y1 = 3+};++static __inline unsigned int+get_BFEnd_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 12)) & 0x3f);+}++static __inline unsigned int+get_BFOpcodeExtension_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 24)) & 0xf);+}++static __inline unsigned int+get_BFStart_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 18)) & 0x3f);+}++static __inline unsigned int+get_BrOff_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 31)) & 0x0000003f) |+ (((unsigned int)(n >> 37)) & 0x0001ffc0);+}++static __inline unsigned int+get_BrType_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 54)) & 0x1f);+}++static __inline unsigned int+get_Dest_Imm8_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 31)) & 0x0000003f) |+ (((unsigned int)(n >> 43)) & 0x000000c0);+}++static __inline unsigned int+get_Dest_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 0)) & 0x3f);+}++static __inline unsigned int+get_Dest_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 31)) & 0x3f);+}++static __inline unsigned int+get_Dest_Y0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 0)) & 0x3f);+}++static __inline unsigned int+get_Dest_Y1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 31)) & 0x3f);+}++static __inline unsigned int+get_Imm16_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 12)) & 0xffff);+}++static __inline unsigned int+get_Imm16_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 43)) & 0xffff);+}++static __inline unsigned int+get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 20)) & 0xff);+}++static __inline unsigned int+get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 51)) & 0xff);+}++static __inline unsigned int+get_Imm8_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 12)) & 0xff);+}++static __inline unsigned int+get_Imm8_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 43)) & 0xff);+}++static __inline unsigned int+get_Imm8_Y0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 12)) & 0xff);+}++static __inline unsigned int+get_Imm8_Y1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 43)) & 0xff);+}++static __inline unsigned int+get_JumpOff_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 31)) & 0x7ffffff);+}++static __inline unsigned int+get_JumpOpcodeExtension_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 58)) & 0x1);+}++static __inline unsigned int+get_MF_Imm14_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 37)) & 0x3fff);+}++static __inline unsigned int+get_MT_Imm14_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 31)) & 0x0000003f) |+ (((unsigned int)(n >> 37)) & 0x00003fc0);+}++static __inline unsigned int+get_Mode(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 62)) & 0x3);+}++static __inline unsigned int+get_Opcode_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 28)) & 0x7);+}++static __inline unsigned int+get_Opcode_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 59)) & 0x7);+}++static __inline unsigned int+get_Opcode_Y0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 27)) & 0xf);+}++static __inline unsigned int+get_Opcode_Y1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 58)) & 0xf);+}++static __inline unsigned int+get_Opcode_Y2(tilegx_bundle_bits n)+{+ return (((n >> 26)) & 0x00000001) |+ (((unsigned int)(n >> 56)) & 0x00000002);+}++static __inline unsigned int+get_RRROpcodeExtension_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 18)) & 0x3ff);+}++static __inline unsigned int+get_RRROpcodeExtension_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 49)) & 0x3ff);+}++static __inline unsigned int+get_RRROpcodeExtension_Y0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 18)) & 0x3);+}++static __inline unsigned int+get_RRROpcodeExtension_Y1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 49)) & 0x3);+}++static __inline unsigned int+get_ShAmt_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 12)) & 0x3f);+}++static __inline unsigned int+get_ShAmt_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 43)) & 0x3f);+}++static __inline unsigned int+get_ShAmt_Y0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 12)) & 0x3f);+}++static __inline unsigned int+get_ShAmt_Y1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 43)) & 0x3f);+}++static __inline unsigned int+get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 18)) & 0x3ff);+}++static __inline unsigned int+get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 49)) & 0x3ff);+}++static __inline unsigned int+get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 18)) & 0x3);+}++static __inline unsigned int+get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 49)) & 0x3);+}++static __inline unsigned int+get_SrcA_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 6)) & 0x3f);+}++static __inline unsigned int+get_SrcA_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 37)) & 0x3f);+}++static __inline unsigned int+get_SrcA_Y0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 6)) & 0x3f);+}++static __inline unsigned int+get_SrcA_Y1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 37)) & 0x3f);+}++static __inline unsigned int+get_SrcA_Y2(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 20)) & 0x3f);+}++static __inline unsigned int+get_SrcBDest_Y2(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 51)) & 0x3f);+}++static __inline unsigned int+get_SrcB_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 12)) & 0x3f);+}++static __inline unsigned int+get_SrcB_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 43)) & 0x3f);+}++static __inline unsigned int+get_SrcB_Y0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 12)) & 0x3f);+}++static __inline unsigned int+get_SrcB_Y1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 43)) & 0x3f);+}++static __inline unsigned int+get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 12)) & 0x3f);+}++static __inline unsigned int+get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 43)) & 0x3f);+}++static __inline unsigned int+get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num)+{+ const unsigned int n = (unsigned int)num;+ return (((n >> 12)) & 0x3f);+}++static __inline unsigned int+get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n)+{+ return (((unsigned int)(n >> 43)) & 0x3f);+}++static __inline int+sign_extend(int n, int num_bits)+{+ int shift = (int)(sizeof(int) * 8 - num_bits);+ return (n << shift) >> shift;+}++static __inline tilegx_bundle_bits+create_BFEnd_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 12);+}++static __inline tilegx_bundle_bits+create_BFOpcodeExtension_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0xf) << 24);+}++static __inline tilegx_bundle_bits+create_BFStart_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 18);+}++static __inline tilegx_bundle_bits+create_BrOff_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |+ (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37);+}++static __inline tilegx_bundle_bits+create_BrType_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x1f)) << 54);+}++static __inline tilegx_bundle_bits+create_Dest_Imm8_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |+ (((tilegx_bundle_bits)(n & 0x000000c0)) << 43);+}++static __inline tilegx_bundle_bits+create_Dest_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 0);+}++static __inline tilegx_bundle_bits+create_Dest_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 31);+}++static __inline tilegx_bundle_bits+create_Dest_Y0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 0);+}++static __inline tilegx_bundle_bits+create_Dest_Y1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 31);+}++static __inline tilegx_bundle_bits+create_Imm16_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0xffff) << 12);+}++static __inline tilegx_bundle_bits+create_Imm16_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0xffff)) << 43);+}++static __inline tilegx_bundle_bits+create_Imm8OpcodeExtension_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0xff) << 20);+}++static __inline tilegx_bundle_bits+create_Imm8OpcodeExtension_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0xff)) << 51);+}++static __inline tilegx_bundle_bits+create_Imm8_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0xff) << 12);+}++static __inline tilegx_bundle_bits+create_Imm8_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0xff)) << 43);+}++static __inline tilegx_bundle_bits+create_Imm8_Y0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0xff) << 12);+}++static __inline tilegx_bundle_bits+create_Imm8_Y1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0xff)) << 43);+}++static __inline tilegx_bundle_bits+create_JumpOff_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31);+}++static __inline tilegx_bundle_bits+create_JumpOpcodeExtension_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x1)) << 58);+}++static __inline tilegx_bundle_bits+create_MF_Imm14_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3fff)) << 37);+}++static __inline tilegx_bundle_bits+create_MT_Imm14_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |+ (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37);+}++static __inline tilegx_bundle_bits+create_Mode(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3)) << 62);+}++static __inline tilegx_bundle_bits+create_Opcode_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x7) << 28);+}++static __inline tilegx_bundle_bits+create_Opcode_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x7)) << 59);+}++static __inline tilegx_bundle_bits+create_Opcode_Y0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0xf) << 27);+}++static __inline tilegx_bundle_bits+create_Opcode_Y1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0xf)) << 58);+}++static __inline tilegx_bundle_bits+create_Opcode_Y2(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x00000001) << 26) |+ (((tilegx_bundle_bits)(n & 0x00000002)) << 56);+}++static __inline tilegx_bundle_bits+create_RRROpcodeExtension_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3ff) << 18);+}++static __inline tilegx_bundle_bits+create_RRROpcodeExtension_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);+}++static __inline tilegx_bundle_bits+create_RRROpcodeExtension_Y0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3) << 18);+}++static __inline tilegx_bundle_bits+create_RRROpcodeExtension_Y1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3)) << 49);+}++static __inline tilegx_bundle_bits+create_ShAmt_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 12);+}++static __inline tilegx_bundle_bits+create_ShAmt_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);+}++static __inline tilegx_bundle_bits+create_ShAmt_Y0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 12);+}++static __inline tilegx_bundle_bits+create_ShAmt_Y1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);+}++static __inline tilegx_bundle_bits+create_ShiftOpcodeExtension_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3ff) << 18);+}++static __inline tilegx_bundle_bits+create_ShiftOpcodeExtension_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);+}++static __inline tilegx_bundle_bits+create_ShiftOpcodeExtension_Y0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3) << 18);+}++static __inline tilegx_bundle_bits+create_ShiftOpcodeExtension_Y1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3)) << 49);+}++static __inline tilegx_bundle_bits+create_SrcA_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 6);+}++static __inline tilegx_bundle_bits+create_SrcA_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 37);+}++static __inline tilegx_bundle_bits+create_SrcA_Y0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 6);+}++static __inline tilegx_bundle_bits+create_SrcA_Y1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 37);+}++static __inline tilegx_bundle_bits+create_SrcA_Y2(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 20);+}++static __inline tilegx_bundle_bits+create_SrcBDest_Y2(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 51);+}++static __inline tilegx_bundle_bits+create_SrcB_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 12);+}++static __inline tilegx_bundle_bits+create_SrcB_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);+}++static __inline tilegx_bundle_bits+create_SrcB_Y0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 12);+}++static __inline tilegx_bundle_bits+create_SrcB_Y1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);+}++static __inline tilegx_bundle_bits+create_UnaryOpcodeExtension_X0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 12);+}++static __inline tilegx_bundle_bits+create_UnaryOpcodeExtension_X1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);+}++static __inline tilegx_bundle_bits+create_UnaryOpcodeExtension_Y0(int num)+{+ const unsigned int n = (unsigned int)num;+ return ((n & 0x3f) << 12);+}++static __inline tilegx_bundle_bits+create_UnaryOpcodeExtension_Y1(int num)+{+ const unsigned int n = (unsigned int)num;+ return (((tilegx_bundle_bits)(n & 0x3f)) << 43);+}++const struct tilegx_opcode tilegx_opcodes[336] =+{+ { "bpt", TILEGX_OPC_BPT, 0x2, 0, TREG_ZERO, 0,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffffffff80000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a44ae00000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "info", TILEGX_OPC_INFO, 0xf, 1, TREG_ZERO, 1,+ { { 0 }, { 1 }, { 2 }, { 3 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00fffULL,+ 0xfff807ff80000000ULL,+ 0x0000000078000fffULL,+ 0x3c0007ff80000000ULL,+ 0ULL+ },+ {+ 0x0000000040300fffULL,+ 0x181807ff80000000ULL,+ 0x0000000010000fffULL,+ 0x0c0007ff80000000ULL,+ -1ULL+ }+#endif+ },+ { "infol", TILEGX_OPC_INFOL, 0x3, 1, TREG_ZERO, 1,+ { { 4 }, { 5 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc000000070000fffULL,+ 0xf80007ff80000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000070000fffULL,+ 0x380007ff80000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ld4s_tls", TILEGX_OPC_LD4S_TLS, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1858000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ld_tls", TILEGX_OPC_LD_TLS, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18a0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "move", TILEGX_OPC_MOVE, 0xf, 2, TREG_ZERO, 1,+ { { 8, 9 }, { 6, 7 }, { 10, 11 }, { 12, 13 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0xfffff80000000000ULL,+ 0x00000000780ff000ULL,+ 0x3c07f80000000000ULL,+ 0ULL+ },+ {+ 0x000000005107f000ULL,+ 0x283bf80000000000ULL,+ 0x00000000500bf000ULL,+ 0x2c05f80000000000ULL,+ -1ULL+ }+#endif+ },+ { "movei", TILEGX_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1,+ { { 8, 0 }, { 6, 1 }, { 10, 2 }, { 12, 3 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00fc0ULL,+ 0xfff807e000000000ULL,+ 0x0000000078000fc0ULL,+ 0x3c0007e000000000ULL,+ 0ULL+ },+ {+ 0x0000000040100fc0ULL,+ 0x180807e000000000ULL,+ 0x0000000000000fc0ULL,+ 0x040007e000000000ULL,+ -1ULL+ }+#endif+ },+ { "moveli", TILEGX_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1,+ { { 8, 4 }, { 6, 5 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc000000070000fc0ULL,+ 0xf80007e000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000010000fc0ULL,+ 0x000007e000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "prefetch", TILEGX_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff81f80000000ULL,+ 0ULL,+ 0ULL,+ 0xc3f8000004000000ULL+ },+ {+ -1ULL,+ 0x286a801f80000000ULL,+ -1ULL,+ -1ULL,+ 0x41f8000004000000ULL+ }+#endif+ },+ { "prefetch_add_l1", TILEGX_OPC_PREFETCH_ADD_L1, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8001f80000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1840001f80000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "prefetch_add_l1_fault", TILEGX_OPC_PREFETCH_ADD_L1_FAULT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8001f80000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1838001f80000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "prefetch_add_l2", TILEGX_OPC_PREFETCH_ADD_L2, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8001f80000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1850001f80000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "prefetch_add_l2_fault", TILEGX_OPC_PREFETCH_ADD_L2_FAULT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8001f80000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1848001f80000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "prefetch_add_l3", TILEGX_OPC_PREFETCH_ADD_L3, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8001f80000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1860001f80000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "prefetch_add_l3_fault", TILEGX_OPC_PREFETCH_ADD_L3_FAULT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8001f80000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1858001f80000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "prefetch_l1", TILEGX_OPC_PREFETCH_L1, 0x12, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff81f80000000ULL,+ 0ULL,+ 0ULL,+ 0xc3f8000004000000ULL+ },+ {+ -1ULL,+ 0x286a801f80000000ULL,+ -1ULL,+ -1ULL,+ 0x41f8000004000000ULL+ }+#endif+ },+ { "prefetch_l1_fault", TILEGX_OPC_PREFETCH_L1_FAULT, 0x12, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff81f80000000ULL,+ 0ULL,+ 0ULL,+ 0xc3f8000004000000ULL+ },+ {+ -1ULL,+ 0x286a781f80000000ULL,+ -1ULL,+ -1ULL,+ 0x41f8000000000000ULL+ }+#endif+ },+ { "prefetch_l2", TILEGX_OPC_PREFETCH_L2, 0x12, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff81f80000000ULL,+ 0ULL,+ 0ULL,+ 0xc3f8000004000000ULL+ },+ {+ -1ULL,+ 0x286a901f80000000ULL,+ -1ULL,+ -1ULL,+ 0x43f8000004000000ULL+ }+#endif+ },+ { "prefetch_l2_fault", TILEGX_OPC_PREFETCH_L2_FAULT, 0x12, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff81f80000000ULL,+ 0ULL,+ 0ULL,+ 0xc3f8000004000000ULL+ },+ {+ -1ULL,+ 0x286a881f80000000ULL,+ -1ULL,+ -1ULL,+ 0x43f8000000000000ULL+ }+#endif+ },+ { "prefetch_l3", TILEGX_OPC_PREFETCH_L3, 0x12, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff81f80000000ULL,+ 0ULL,+ 0ULL,+ 0xc3f8000004000000ULL+ },+ {+ -1ULL,+ 0x286aa01f80000000ULL,+ -1ULL,+ -1ULL,+ 0x83f8000000000000ULL+ }+#endif+ },+ { "prefetch_l3_fault", TILEGX_OPC_PREFETCH_L3_FAULT, 0x12, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff81f80000000ULL,+ 0ULL,+ 0ULL,+ 0xc3f8000004000000ULL+ },+ {+ -1ULL,+ 0x286a981f80000000ULL,+ -1ULL,+ -1ULL,+ 0x81f8000004000000ULL+ }+#endif+ },+ { "raise", TILEGX_OPC_RAISE, 0x2, 0, TREG_ZERO, 1,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffffffff80000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a44ae80000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "add", TILEGX_OPC_ADD, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x00000000500c0000ULL,+ 0x2806000000000000ULL,+ 0x0000000028040000ULL,+ 0x1802000000000000ULL,+ -1ULL+ }+#endif+ },+ { "addi", TILEGX_OPC_ADDI, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0x0000000078000000ULL,+ 0x3c00000000000000ULL,+ 0ULL+ },+ {+ 0x0000000040100000ULL,+ 0x1808000000000000ULL,+ 0ULL,+ 0x0400000000000000ULL,+ -1ULL+ }+#endif+ },+ { "addli", TILEGX_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc000000070000000ULL,+ 0xf800000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000010000000ULL,+ 0ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "addx", TILEGX_OPC_ADDX, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000050080000ULL,+ 0x2804000000000000ULL,+ 0x0000000028000000ULL,+ 0x1800000000000000ULL,+ -1ULL+ }+#endif+ },+ { "addxi", TILEGX_OPC_ADDXI, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0x0000000078000000ULL,+ 0x3c00000000000000ULL,+ 0ULL+ },+ {+ 0x0000000040200000ULL,+ 0x1810000000000000ULL,+ 0x0000000008000000ULL,+ 0x0800000000000000ULL,+ -1ULL+ }+#endif+ },+ { "addxli", TILEGX_OPC_ADDXLI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc000000070000000ULL,+ 0xf800000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000020000000ULL,+ 0x0800000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "addxsc", TILEGX_OPC_ADDXSC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050040000ULL,+ 0x2802000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "and", TILEGX_OPC_AND, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000050100000ULL,+ 0x2808000000000000ULL,+ 0x0000000050000000ULL,+ 0x2c00000000000000ULL,+ -1ULL+ }+#endif+ },+ { "andi", TILEGX_OPC_ANDI, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0x0000000078000000ULL,+ 0x3c00000000000000ULL,+ 0ULL+ },+ {+ 0x0000000040300000ULL,+ 0x1818000000000000ULL,+ 0x0000000010000000ULL,+ 0x0c00000000000000ULL,+ -1ULL+ }+#endif+ },+ { "beqz", TILEGX_OPC_BEQZ, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1440000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "beqzt", TILEGX_OPC_BEQZT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1400000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bfexts", TILEGX_OPC_BFEXTS, 0x1, 4, TREG_ZERO, 1,+ { { 8, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007f000000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000034000000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bfextu", TILEGX_OPC_BFEXTU, 0x1, 4, TREG_ZERO, 1,+ { { 8, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007f000000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000035000000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bfins", TILEGX_OPC_BFINS, 0x1, 4, TREG_ZERO, 1,+ { { 23, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007f000000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000036000000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bgez", TILEGX_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x14c0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bgezt", TILEGX_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1480000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bgtz", TILEGX_OPC_BGTZ, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1540000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bgtzt", TILEGX_OPC_BGTZT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1500000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "blbc", TILEGX_OPC_BLBC, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x15c0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "blbct", TILEGX_OPC_BLBCT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1580000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "blbs", TILEGX_OPC_BLBS, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1640000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "blbst", TILEGX_OPC_BLBST, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1600000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "blez", TILEGX_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x16c0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "blezt", TILEGX_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1680000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bltz", TILEGX_OPC_BLTZ, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1740000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bltzt", TILEGX_OPC_BLTZT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1700000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bnez", TILEGX_OPC_BNEZ, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x17c0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "bnezt", TILEGX_OPC_BNEZT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xffc0000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1780000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "clz", TILEGX_OPC_CLZ, 0x5, 2, TREG_ZERO, 1,+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0ULL,+ 0x00000000780ff000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051481000ULL,+ -1ULL,+ 0x00000000300c1000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmoveqz", TILEGX_OPC_CMOVEQZ, 0x5, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050140000ULL,+ -1ULL,+ 0x0000000048000000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmovnez", TILEGX_OPC_CMOVNEZ, 0x5, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050180000ULL,+ -1ULL,+ 0x0000000048040000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmpeq", TILEGX_OPC_CMPEQ, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x00000000501c0000ULL,+ 0x280a000000000000ULL,+ 0x0000000040000000ULL,+ 0x2404000000000000ULL,+ -1ULL+ }+#endif+ },+ { "cmpeqi", TILEGX_OPC_CMPEQI, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0x0000000078000000ULL,+ 0x3c00000000000000ULL,+ 0ULL+ },+ {+ 0x0000000040400000ULL,+ 0x1820000000000000ULL,+ 0x0000000018000000ULL,+ 0x1000000000000000ULL,+ -1ULL+ }+#endif+ },+ { "cmpexch", TILEGX_OPC_CMPEXCH, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x280e000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmpexch4", TILEGX_OPC_CMPEXCH4, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x280c000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmples", TILEGX_OPC_CMPLES, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000050200000ULL,+ 0x2810000000000000ULL,+ 0x0000000038000000ULL,+ 0x2000000000000000ULL,+ -1ULL+ }+#endif+ },+ { "cmpleu", TILEGX_OPC_CMPLEU, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000050240000ULL,+ 0x2812000000000000ULL,+ 0x0000000038040000ULL,+ 0x2002000000000000ULL,+ -1ULL+ }+#endif+ },+ { "cmplts", TILEGX_OPC_CMPLTS, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000050280000ULL,+ 0x2814000000000000ULL,+ 0x0000000038080000ULL,+ 0x2004000000000000ULL,+ -1ULL+ }+#endif+ },+ { "cmpltsi", TILEGX_OPC_CMPLTSI, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0x0000000078000000ULL,+ 0x3c00000000000000ULL,+ 0ULL+ },+ {+ 0x0000000040500000ULL,+ 0x1828000000000000ULL,+ 0x0000000020000000ULL,+ 0x1400000000000000ULL,+ -1ULL+ }+#endif+ },+ { "cmpltu", TILEGX_OPC_CMPLTU, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x00000000502c0000ULL,+ 0x2816000000000000ULL,+ 0x00000000380c0000ULL,+ 0x2006000000000000ULL,+ -1ULL+ }+#endif+ },+ { "cmpltui", TILEGX_OPC_CMPLTUI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000040600000ULL,+ 0x1830000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmpne", TILEGX_OPC_CMPNE, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000050300000ULL,+ 0x2818000000000000ULL,+ 0x0000000040040000ULL,+ 0x2406000000000000ULL,+ -1ULL+ }+#endif+ },+ { "cmul", TILEGX_OPC_CMUL, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000504c0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmula", TILEGX_OPC_CMULA, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050380000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmulaf", TILEGX_OPC_CMULAF, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050340000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmulf", TILEGX_OPC_CMULF, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050400000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmulfr", TILEGX_OPC_CMULFR, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000503c0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmulh", TILEGX_OPC_CMULH, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050480000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "cmulhr", TILEGX_OPC_CMULHR, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050440000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "crc32_32", TILEGX_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050500000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "crc32_8", TILEGX_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050540000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ctz", TILEGX_OPC_CTZ, 0x5, 2, TREG_ZERO, 1,+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0ULL,+ 0x00000000780ff000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051482000ULL,+ -1ULL,+ 0x00000000300c2000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "dblalign", TILEGX_OPC_DBLALIGN, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050640000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "dblalign2", TILEGX_OPC_DBLALIGN2, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050580000ULL,+ 0x281a000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "dblalign4", TILEGX_OPC_DBLALIGN4, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000505c0000ULL,+ 0x281c000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "dblalign6", TILEGX_OPC_DBLALIGN6, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050600000ULL,+ 0x281e000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "drain", TILEGX_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a080000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "dtlbpr", TILEGX_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a100000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "exch", TILEGX_OPC_EXCH, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x2822000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "exch4", TILEGX_OPC_EXCH4, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x2820000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fdouble_add_flags", TILEGX_OPC_FDOUBLE_ADD_FLAGS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000506c0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fdouble_addsub", TILEGX_OPC_FDOUBLE_ADDSUB, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050680000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fdouble_mul_flags", TILEGX_OPC_FDOUBLE_MUL_FLAGS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050700000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fdouble_pack1", TILEGX_OPC_FDOUBLE_PACK1, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050740000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fdouble_pack2", TILEGX_OPC_FDOUBLE_PACK2, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050780000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fdouble_sub_flags", TILEGX_OPC_FDOUBLE_SUB_FLAGS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000507c0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fdouble_unpack_max", TILEGX_OPC_FDOUBLE_UNPACK_MAX, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050800000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fdouble_unpack_min", TILEGX_OPC_FDOUBLE_UNPACK_MIN, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050840000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fetchadd", TILEGX_OPC_FETCHADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x282a000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fetchadd4", TILEGX_OPC_FETCHADD4, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x2824000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fetchaddgez", TILEGX_OPC_FETCHADDGEZ, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x2828000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fetchaddgez4", TILEGX_OPC_FETCHADDGEZ4, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x2826000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fetchand", TILEGX_OPC_FETCHAND, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x282e000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fetchand4", TILEGX_OPC_FETCHAND4, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x282c000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fetchor", TILEGX_OPC_FETCHOR, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x2832000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fetchor4", TILEGX_OPC_FETCHOR4, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x2830000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "finv", TILEGX_OPC_FINV, 0x2, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a180000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "flush", TILEGX_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a280000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "flushwb", TILEGX_OPC_FLUSHWB, 0x2, 0, TREG_ZERO, 1,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a200000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fnop", TILEGX_OPC_FNOP, 0xf, 0, TREG_ZERO, 1,+ { { }, { }, { }, { }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0xfffff80000000000ULL,+ 0x00000000780ff000ULL,+ 0x3c07f80000000000ULL,+ 0ULL+ },+ {+ 0x0000000051483000ULL,+ 0x286a300000000000ULL,+ 0x00000000300c3000ULL,+ 0x1c06400000000000ULL,+ -1ULL+ }+#endif+ },+ { "fsingle_add1", TILEGX_OPC_FSINGLE_ADD1, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050880000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fsingle_addsub2", TILEGX_OPC_FSINGLE_ADDSUB2, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000508c0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fsingle_mul1", TILEGX_OPC_FSINGLE_MUL1, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050900000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fsingle_mul2", TILEGX_OPC_FSINGLE_MUL2, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050940000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fsingle_pack1", TILEGX_OPC_FSINGLE_PACK1, 0x5, 2, TREG_ZERO, 1,+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0ULL,+ 0x00000000780ff000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051484000ULL,+ -1ULL,+ 0x00000000300c4000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fsingle_pack2", TILEGX_OPC_FSINGLE_PACK2, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050980000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "fsingle_sub1", TILEGX_OPC_FSINGLE_SUB1, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000509c0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "icoh", TILEGX_OPC_ICOH, 0x2, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a380000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ill", TILEGX_OPC_ILL, 0xa, 0, TREG_ZERO, 1,+ { { 0, }, { }, { 0, }, { }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0x3c07f80000000000ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a400000000000ULL,+ -1ULL,+ 0x1c06480000000000ULL,+ -1ULL+ }+#endif+ },+ { "inv", TILEGX_OPC_INV, 0x2, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a480000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "iret", TILEGX_OPC_IRET, 0x2, 0, TREG_ZERO, 1,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a500000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "j", TILEGX_OPC_J, 0x2, 1, TREG_ZERO, 1,+ { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfc00000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x2400000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "jal", TILEGX_OPC_JAL, 0x2, 1, TREG_LR, 1,+ { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfc00000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x2000000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "jalr", TILEGX_OPC_JALR, 0xa, 1, TREG_LR, 1,+ { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0x3c07f80000000000ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a600000000000ULL,+ -1ULL,+ 0x1c06580000000000ULL,+ -1ULL+ }+#endif+ },+ { "jalrp", TILEGX_OPC_JALRP, 0xa, 1, TREG_LR, 1,+ { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0x3c07f80000000000ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a580000000000ULL,+ -1ULL,+ 0x1c06500000000000ULL,+ -1ULL+ }+#endif+ },+ { "jr", TILEGX_OPC_JR, 0xa, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0x3c07f80000000000ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a700000000000ULL,+ -1ULL,+ 0x1c06680000000000ULL,+ -1ULL+ }+#endif+ },+ { "jrp", TILEGX_OPC_JRP, 0xa, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0x3c07f80000000000ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286a680000000000ULL,+ -1ULL,+ 0x1c06600000000000ULL,+ -1ULL+ }+#endif+ },+ { "ld", TILEGX_OPC_LD, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x286ae80000000000ULL,+ -1ULL,+ -1ULL,+ 0x8200000004000000ULL+ }+#endif+ },+ { "ld1s", TILEGX_OPC_LD1S, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x286a780000000000ULL,+ -1ULL,+ -1ULL,+ 0x4000000000000000ULL+ }+#endif+ },+ { "ld1s_add", TILEGX_OPC_LD1S_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1838000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ld1u", TILEGX_OPC_LD1U, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x286a800000000000ULL,+ -1ULL,+ -1ULL,+ 0x4000000004000000ULL+ }+#endif+ },+ { "ld1u_add", TILEGX_OPC_LD1U_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1840000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ld2s", TILEGX_OPC_LD2S, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x286a880000000000ULL,+ -1ULL,+ -1ULL,+ 0x4200000000000000ULL+ }+#endif+ },+ { "ld2s_add", TILEGX_OPC_LD2S_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1848000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ld2u", TILEGX_OPC_LD2U, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x286a900000000000ULL,+ -1ULL,+ -1ULL,+ 0x4200000004000000ULL+ }+#endif+ },+ { "ld2u_add", TILEGX_OPC_LD2U_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1850000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ld4s", TILEGX_OPC_LD4S, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x286a980000000000ULL,+ -1ULL,+ -1ULL,+ 0x8000000004000000ULL+ }+#endif+ },+ { "ld4s_add", TILEGX_OPC_LD4S_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1858000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ld4u", TILEGX_OPC_LD4U, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x286aa00000000000ULL,+ -1ULL,+ -1ULL,+ 0x8200000000000000ULL+ }+#endif+ },+ { "ld4u_add", TILEGX_OPC_LD4U_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1860000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ld_add", TILEGX_OPC_LD_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18a0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldna", TILEGX_OPC_LDNA, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286aa80000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldna_add", TILEGX_OPC_LDNA_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18a8000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt", TILEGX_OPC_LDNT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286ae00000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt1s", TILEGX_OPC_LDNT1S, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286ab00000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt1s_add", TILEGX_OPC_LDNT1S_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1868000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt1u", TILEGX_OPC_LDNT1U, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286ab80000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt1u_add", TILEGX_OPC_LDNT1U_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1870000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt2s", TILEGX_OPC_LDNT2S, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286ac00000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt2s_add", TILEGX_OPC_LDNT2S_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1878000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt2u", TILEGX_OPC_LDNT2U, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286ac80000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt2u_add", TILEGX_OPC_LDNT2U_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1880000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt4s", TILEGX_OPC_LDNT4S, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286ad00000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt4s_add", TILEGX_OPC_LDNT4S_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1888000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt4u", TILEGX_OPC_LDNT4U, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286ad80000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt4u_add", TILEGX_OPC_LDNT4U_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1890000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "ldnt_add", TILEGX_OPC_LDNT_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1898000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "lnk", TILEGX_OPC_LNK, 0xa, 1, TREG_ZERO, 1,+ { { 0, }, { 6 }, { 0, }, { 12 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0x3c07f80000000000ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286af00000000000ULL,+ -1ULL,+ 0x1c06700000000000ULL,+ -1ULL+ }+#endif+ },+ { "mf", TILEGX_OPC_MF, 0x2, 0, TREG_ZERO, 1,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286af80000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mfspr", TILEGX_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 6, 27 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18b0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mm", TILEGX_OPC_MM, 0x1, 4, TREG_ZERO, 1,+ { { 23, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007f000000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000037000000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mnz", TILEGX_OPC_MNZ, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000050a00000ULL,+ 0x2834000000000000ULL,+ 0x0000000048080000ULL,+ 0x2804000000000000ULL,+ -1ULL+ }+#endif+ },+ { "mtspr", TILEGX_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 28, 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18b8000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mul_hs_hs", TILEGX_OPC_MUL_HS_HS, 0x5, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050d40000ULL,+ -1ULL,+ 0x0000000068000000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mul_hs_hu", TILEGX_OPC_MUL_HS_HU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050d80000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mul_hs_ls", TILEGX_OPC_MUL_HS_LS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050dc0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mul_hs_lu", TILEGX_OPC_MUL_HS_LU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050e00000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mul_hu_hu", TILEGX_OPC_MUL_HU_HU, 0x5, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050e40000ULL,+ -1ULL,+ 0x0000000068040000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mul_hu_ls", TILEGX_OPC_MUL_HU_LS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050e80000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mul_hu_lu", TILEGX_OPC_MUL_HU_LU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050ec0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mul_ls_ls", TILEGX_OPC_MUL_LS_LS, 0x5, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050f00000ULL,+ -1ULL,+ 0x0000000068080000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mul_ls_lu", TILEGX_OPC_MUL_LS_LU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050f40000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mul_lu_lu", TILEGX_OPC_MUL_LU_LU, 0x5, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050f80000ULL,+ -1ULL,+ 0x00000000680c0000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mula_hs_hs", TILEGX_OPC_MULA_HS_HS, 0x5, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050a80000ULL,+ -1ULL,+ 0x0000000070000000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mula_hs_hu", TILEGX_OPC_MULA_HS_HU, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050ac0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mula_hs_ls", TILEGX_OPC_MULA_HS_LS, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050b00000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mula_hs_lu", TILEGX_OPC_MULA_HS_LU, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050b40000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mula_hu_hu", TILEGX_OPC_MULA_HU_HU, 0x5, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050b80000ULL,+ -1ULL,+ 0x0000000070040000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mula_hu_ls", TILEGX_OPC_MULA_HU_LS, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050bc0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mula_hu_lu", TILEGX_OPC_MULA_HU_LU, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050c00000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mula_ls_ls", TILEGX_OPC_MULA_LS_LS, 0x5, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050c40000ULL,+ -1ULL,+ 0x0000000070080000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mula_ls_lu", TILEGX_OPC_MULA_LS_LU, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050c80000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mula_lu_lu", TILEGX_OPC_MULA_LU_LU, 0x5, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050cc0000ULL,+ -1ULL,+ 0x00000000700c0000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mulax", TILEGX_OPC_MULAX, 0x5, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050a40000ULL,+ -1ULL,+ 0x0000000040080000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mulx", TILEGX_OPC_MULX, 0x5, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0x00000000780c0000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000050d00000ULL,+ -1ULL,+ 0x00000000400c0000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "mz", TILEGX_OPC_MZ, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000050fc0000ULL,+ 0x2836000000000000ULL,+ 0x00000000480c0000ULL,+ 0x2806000000000000ULL,+ -1ULL+ }+#endif+ },+ { "nap", TILEGX_OPC_NAP, 0x2, 0, TREG_ZERO, 0,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286b000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "nop", TILEGX_OPC_NOP, 0xf, 0, TREG_ZERO, 1,+ { { }, { }, { }, { }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0xfffff80000000000ULL,+ 0x00000000780ff000ULL,+ 0x3c07f80000000000ULL,+ 0ULL+ },+ {+ 0x0000000051485000ULL,+ 0x286b080000000000ULL,+ 0x00000000300c5000ULL,+ 0x1c06780000000000ULL,+ -1ULL+ }+#endif+ },+ { "nor", TILEGX_OPC_NOR, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051000000ULL,+ 0x2838000000000000ULL,+ 0x0000000050040000ULL,+ 0x2c02000000000000ULL,+ -1ULL+ }+#endif+ },+ { "or", TILEGX_OPC_OR, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051040000ULL,+ 0x283a000000000000ULL,+ 0x0000000050080000ULL,+ 0x2c04000000000000ULL,+ -1ULL+ }+#endif+ },+ { "ori", TILEGX_OPC_ORI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000040700000ULL,+ 0x18c0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "pcnt", TILEGX_OPC_PCNT, 0x5, 2, TREG_ZERO, 1,+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0ULL,+ 0x00000000780ff000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051486000ULL,+ -1ULL,+ 0x00000000300c6000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "revbits", TILEGX_OPC_REVBITS, 0x5, 2, TREG_ZERO, 1,+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0ULL,+ 0x00000000780ff000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051487000ULL,+ -1ULL,+ 0x00000000300c7000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "revbytes", TILEGX_OPC_REVBYTES, 0x5, 2, TREG_ZERO, 1,+ { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0ULL,+ 0x00000000780ff000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051488000ULL,+ -1ULL,+ 0x00000000300c8000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "rotl", TILEGX_OPC_ROTL, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051080000ULL,+ 0x283c000000000000ULL,+ 0x0000000058000000ULL,+ 0x3000000000000000ULL,+ -1ULL+ }+#endif+ },+ { "rotli", TILEGX_OPC_ROTLI, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000060040000ULL,+ 0x3002000000000000ULL,+ 0x0000000078000000ULL,+ 0x3800000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shl", TILEGX_OPC_SHL, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051280000ULL,+ 0x284c000000000000ULL,+ 0x0000000058040000ULL,+ 0x3002000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shl16insli", TILEGX_OPC_SHL16INSLI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc000000070000000ULL,+ 0xf800000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000070000000ULL,+ 0x3800000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "shl1add", TILEGX_OPC_SHL1ADD, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051100000ULL,+ 0x2840000000000000ULL,+ 0x0000000030000000ULL,+ 0x1c00000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shl1addx", TILEGX_OPC_SHL1ADDX, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x00000000510c0000ULL,+ 0x283e000000000000ULL,+ 0x0000000060040000ULL,+ 0x3402000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shl2add", TILEGX_OPC_SHL2ADD, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051180000ULL,+ 0x2844000000000000ULL,+ 0x0000000030040000ULL,+ 0x1c02000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shl2addx", TILEGX_OPC_SHL2ADDX, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051140000ULL,+ 0x2842000000000000ULL,+ 0x0000000060080000ULL,+ 0x3404000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shl3add", TILEGX_OPC_SHL3ADD, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051200000ULL,+ 0x2848000000000000ULL,+ 0x0000000030080000ULL,+ 0x1c04000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shl3addx", TILEGX_OPC_SHL3ADDX, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x00000000511c0000ULL,+ 0x2846000000000000ULL,+ 0x00000000600c0000ULL,+ 0x3406000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shli", TILEGX_OPC_SHLI, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000060080000ULL,+ 0x3004000000000000ULL,+ 0x0000000078040000ULL,+ 0x3802000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shlx", TILEGX_OPC_SHLX, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051240000ULL,+ 0x284a000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "shlxi", TILEGX_OPC_SHLXI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000600c0000ULL,+ 0x3006000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "shrs", TILEGX_OPC_SHRS, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x00000000512c0000ULL,+ 0x284e000000000000ULL,+ 0x0000000058080000ULL,+ 0x3004000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shrsi", TILEGX_OPC_SHRSI, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000060100000ULL,+ 0x3008000000000000ULL,+ 0x0000000078080000ULL,+ 0x3804000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shru", TILEGX_OPC_SHRU, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051340000ULL,+ 0x2852000000000000ULL,+ 0x00000000580c0000ULL,+ 0x3006000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shrui", TILEGX_OPC_SHRUI, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000060140000ULL,+ 0x300a000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3806000000000000ULL,+ -1ULL+ }+#endif+ },+ { "shrux", TILEGX_OPC_SHRUX, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051300000ULL,+ 0x2850000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "shruxi", TILEGX_OPC_SHRUXI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000060180000ULL,+ 0x300c000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "shufflebytes", TILEGX_OPC_SHUFFLEBYTES, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051380000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "st", TILEGX_OPC_ST, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x2862000000000000ULL,+ -1ULL,+ -1ULL,+ 0xc200000004000000ULL+ }+#endif+ },+ { "st1", TILEGX_OPC_ST1, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x2854000000000000ULL,+ -1ULL,+ -1ULL,+ 0xc000000000000000ULL+ }+#endif+ },+ { "st1_add", TILEGX_OPC_ST1_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18c8000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "st2", TILEGX_OPC_ST2, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x2856000000000000ULL,+ -1ULL,+ -1ULL,+ 0xc000000004000000ULL+ }+#endif+ },+ { "st2_add", TILEGX_OPC_ST2_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18d0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "st4", TILEGX_OPC_ST4, 0x12, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0xc200000004000000ULL+ },+ {+ -1ULL,+ 0x2858000000000000ULL,+ -1ULL,+ -1ULL,+ 0xc200000000000000ULL+ }+#endif+ },+ { "st4_add", TILEGX_OPC_ST4_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18d8000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "st_add", TILEGX_OPC_ST_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x1900000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "stnt", TILEGX_OPC_STNT, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x2860000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "stnt1", TILEGX_OPC_STNT1, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x285a000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "stnt1_add", TILEGX_OPC_STNT1_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18e0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "stnt2", TILEGX_OPC_STNT2, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x285c000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "stnt2_add", TILEGX_OPC_STNT2_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18e8000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "stnt4", TILEGX_OPC_STNT4, 0x2, 2, TREG_ZERO, 1,+ { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x285e000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "stnt4_add", TILEGX_OPC_STNT4_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18f0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "stnt_add", TILEGX_OPC_STNT_ADD, 0x2, 3, TREG_ZERO, 1,+ { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x18f8000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "sub", TILEGX_OPC_SUB, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051440000ULL,+ 0x2868000000000000ULL,+ 0x00000000280c0000ULL,+ 0x1806000000000000ULL,+ -1ULL+ }+#endif+ },+ { "subx", TILEGX_OPC_SUBX, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000051400000ULL,+ 0x2866000000000000ULL,+ 0x0000000028080000ULL,+ 0x1804000000000000ULL,+ -1ULL+ }+#endif+ },+ { "subxsc", TILEGX_OPC_SUBXSC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000513c0000ULL,+ 0x2864000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "swint0", TILEGX_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286b100000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "swint1", TILEGX_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286b180000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "swint2", TILEGX_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286b200000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "swint3", TILEGX_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0,+ { { 0, }, { }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286b280000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "tblidxb0", TILEGX_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1,+ { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0ULL,+ 0x00000000780ff000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051489000ULL,+ -1ULL,+ 0x00000000300c9000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "tblidxb1", TILEGX_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1,+ { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0ULL,+ 0x00000000780ff000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x000000005148a000ULL,+ -1ULL,+ 0x00000000300ca000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "tblidxb2", TILEGX_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1,+ { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0ULL,+ 0x00000000780ff000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x000000005148b000ULL,+ -1ULL,+ 0x00000000300cb000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "tblidxb3", TILEGX_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1,+ { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffff000ULL,+ 0ULL,+ 0x00000000780ff000ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x000000005148c000ULL,+ -1ULL,+ 0x00000000300cc000ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1add", TILEGX_OPC_V1ADD, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051500000ULL,+ 0x286e000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1addi", TILEGX_OPC_V1ADDI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000040800000ULL,+ 0x1908000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1adduc", TILEGX_OPC_V1ADDUC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000514c0000ULL,+ 0x286c000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1adiffu", TILEGX_OPC_V1ADIFFU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051540000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1avgu", TILEGX_OPC_V1AVGU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051580000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1cmpeq", TILEGX_OPC_V1CMPEQ, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000515c0000ULL,+ 0x2870000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1cmpeqi", TILEGX_OPC_V1CMPEQI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000040900000ULL,+ 0x1910000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1cmples", TILEGX_OPC_V1CMPLES, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051600000ULL,+ 0x2872000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1cmpleu", TILEGX_OPC_V1CMPLEU, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051640000ULL,+ 0x2874000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1cmplts", TILEGX_OPC_V1CMPLTS, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051680000ULL,+ 0x2876000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1cmpltsi", TILEGX_OPC_V1CMPLTSI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000040a00000ULL,+ 0x1918000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1cmpltu", TILEGX_OPC_V1CMPLTU, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000516c0000ULL,+ 0x2878000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1cmpltui", TILEGX_OPC_V1CMPLTUI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000040b00000ULL,+ 0x1920000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1cmpne", TILEGX_OPC_V1CMPNE, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051700000ULL,+ 0x287a000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1ddotpu", TILEGX_OPC_V1DDOTPU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052880000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1ddotpua", TILEGX_OPC_V1DDOTPUA, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052840000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1ddotpus", TILEGX_OPC_V1DDOTPUS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051780000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1ddotpusa", TILEGX_OPC_V1DDOTPUSA, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051740000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1dotp", TILEGX_OPC_V1DOTP, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051880000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1dotpa", TILEGX_OPC_V1DOTPA, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000517c0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1dotpu", TILEGX_OPC_V1DOTPU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052900000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1dotpua", TILEGX_OPC_V1DOTPUA, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000528c0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1dotpus", TILEGX_OPC_V1DOTPUS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051840000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1dotpusa", TILEGX_OPC_V1DOTPUSA, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051800000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1int_h", TILEGX_OPC_V1INT_H, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000518c0000ULL,+ 0x287c000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1int_l", TILEGX_OPC_V1INT_L, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051900000ULL,+ 0x287e000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1maxu", TILEGX_OPC_V1MAXU, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051940000ULL,+ 0x2880000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1maxui", TILEGX_OPC_V1MAXUI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000040c00000ULL,+ 0x1928000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1minu", TILEGX_OPC_V1MINU, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051980000ULL,+ 0x2882000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1minui", TILEGX_OPC_V1MINUI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000040d00000ULL,+ 0x1930000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1mnz", TILEGX_OPC_V1MNZ, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000519c0000ULL,+ 0x2884000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1multu", TILEGX_OPC_V1MULTU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051a00000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1mulu", TILEGX_OPC_V1MULU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051a80000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1mulus", TILEGX_OPC_V1MULUS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051a40000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1mz", TILEGX_OPC_V1MZ, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051ac0000ULL,+ 0x2886000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1sadau", TILEGX_OPC_V1SADAU, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051b00000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1sadu", TILEGX_OPC_V1SADU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051b40000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1shl", TILEGX_OPC_V1SHL, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051b80000ULL,+ 0x2888000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1shli", TILEGX_OPC_V1SHLI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000601c0000ULL,+ 0x300e000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1shrs", TILEGX_OPC_V1SHRS, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051bc0000ULL,+ 0x288a000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1shrsi", TILEGX_OPC_V1SHRSI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000060200000ULL,+ 0x3010000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1shru", TILEGX_OPC_V1SHRU, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051c00000ULL,+ 0x288c000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1shrui", TILEGX_OPC_V1SHRUI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000060240000ULL,+ 0x3012000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1sub", TILEGX_OPC_V1SUB, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051c80000ULL,+ 0x2890000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v1subuc", TILEGX_OPC_V1SUBUC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051c40000ULL,+ 0x288e000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2add", TILEGX_OPC_V2ADD, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051d00000ULL,+ 0x2894000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2addi", TILEGX_OPC_V2ADDI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000040e00000ULL,+ 0x1938000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2addsc", TILEGX_OPC_V2ADDSC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051cc0000ULL,+ 0x2892000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2adiffs", TILEGX_OPC_V2ADIFFS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051d40000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2avgs", TILEGX_OPC_V2AVGS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051d80000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2cmpeq", TILEGX_OPC_V2CMPEQ, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051dc0000ULL,+ 0x2896000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2cmpeqi", TILEGX_OPC_V2CMPEQI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000040f00000ULL,+ 0x1940000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2cmples", TILEGX_OPC_V2CMPLES, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051e00000ULL,+ 0x2898000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2cmpleu", TILEGX_OPC_V2CMPLEU, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051e40000ULL,+ 0x289a000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2cmplts", TILEGX_OPC_V2CMPLTS, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051e80000ULL,+ 0x289c000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2cmpltsi", TILEGX_OPC_V2CMPLTSI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000041000000ULL,+ 0x1948000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2cmpltu", TILEGX_OPC_V2CMPLTU, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051ec0000ULL,+ 0x289e000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2cmpltui", TILEGX_OPC_V2CMPLTUI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000041100000ULL,+ 0x1950000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2cmpne", TILEGX_OPC_V2CMPNE, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051f00000ULL,+ 0x28a0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2dotp", TILEGX_OPC_V2DOTP, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051f80000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2dotpa", TILEGX_OPC_V2DOTPA, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051f40000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2int_h", TILEGX_OPC_V2INT_H, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000051fc0000ULL,+ 0x28a2000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2int_l", TILEGX_OPC_V2INT_L, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052000000ULL,+ 0x28a4000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2maxs", TILEGX_OPC_V2MAXS, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052040000ULL,+ 0x28a6000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2maxsi", TILEGX_OPC_V2MAXSI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000041200000ULL,+ 0x1958000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2mins", TILEGX_OPC_V2MINS, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052080000ULL,+ 0x28a8000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2minsi", TILEGX_OPC_V2MINSI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000041300000ULL,+ 0x1960000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2mnz", TILEGX_OPC_V2MNZ, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000520c0000ULL,+ 0x28aa000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2mulfsc", TILEGX_OPC_V2MULFSC, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052100000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2muls", TILEGX_OPC_V2MULS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052140000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2mults", TILEGX_OPC_V2MULTS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052180000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2mz", TILEGX_OPC_V2MZ, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000521c0000ULL,+ 0x28ac000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2packh", TILEGX_OPC_V2PACKH, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052200000ULL,+ 0x28ae000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2packl", TILEGX_OPC_V2PACKL, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052240000ULL,+ 0x28b0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2packuc", TILEGX_OPC_V2PACKUC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052280000ULL,+ 0x28b2000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2sadas", TILEGX_OPC_V2SADAS, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000522c0000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2sadau", TILEGX_OPC_V2SADAU, 0x1, 3, TREG_ZERO, 1,+ { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052300000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2sads", TILEGX_OPC_V2SADS, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052340000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2sadu", TILEGX_OPC_V2SADU, 0x1, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052380000ULL,+ -1ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2shl", TILEGX_OPC_V2SHL, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052400000ULL,+ 0x28b6000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2shli", TILEGX_OPC_V2SHLI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000060280000ULL,+ 0x3014000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2shlsc", TILEGX_OPC_V2SHLSC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000523c0000ULL,+ 0x28b4000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2shrs", TILEGX_OPC_V2SHRS, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052440000ULL,+ 0x28b8000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2shrsi", TILEGX_OPC_V2SHRSI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000602c0000ULL,+ 0x3016000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2shru", TILEGX_OPC_V2SHRU, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052480000ULL,+ 0x28ba000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2shrui", TILEGX_OPC_V2SHRUI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000060300000ULL,+ 0x3018000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2sub", TILEGX_OPC_V2SUB, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052500000ULL,+ 0x28be000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v2subsc", TILEGX_OPC_V2SUBSC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000524c0000ULL,+ 0x28bc000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4add", TILEGX_OPC_V4ADD, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052580000ULL,+ 0x28c2000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4addsc", TILEGX_OPC_V4ADDSC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052540000ULL,+ 0x28c0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4int_h", TILEGX_OPC_V4INT_H, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000525c0000ULL,+ 0x28c4000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4int_l", TILEGX_OPC_V4INT_L, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052600000ULL,+ 0x28c6000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4packsc", TILEGX_OPC_V4PACKSC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052640000ULL,+ 0x28c8000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4shl", TILEGX_OPC_V4SHL, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000526c0000ULL,+ 0x28cc000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4shlsc", TILEGX_OPC_V4SHLSC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052680000ULL,+ 0x28ca000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4shrs", TILEGX_OPC_V4SHRS, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052700000ULL,+ 0x28ce000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4shru", TILEGX_OPC_V4SHRU, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052740000ULL,+ 0x28d0000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4sub", TILEGX_OPC_V4SUB, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x00000000527c0000ULL,+ 0x28d4000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "v4subsc", TILEGX_OPC_V4SUBSC, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000052780000ULL,+ 0x28d2000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "wh64", TILEGX_OPC_WH64, 0x2, 1, TREG_ZERO, 1,+ { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0ULL,+ 0xfffff80000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ -1ULL,+ 0x286b300000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { "xor", TILEGX_OPC_XOR, 0xf, 3, TREG_ZERO, 1,+ { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ffc0000ULL,+ 0xfffe000000000000ULL,+ 0x00000000780c0000ULL,+ 0x3c06000000000000ULL,+ 0ULL+ },+ {+ 0x0000000052800000ULL,+ 0x28d6000000000000ULL,+ 0x00000000500c0000ULL,+ 0x2c06000000000000ULL,+ -1ULL+ }+#endif+ },+ { "xori", TILEGX_OPC_XORI, 0x3, 3, TREG_ZERO, 1,+ { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } },+#ifndef DISASM_ONLY+ {+ 0xc00000007ff00000ULL,+ 0xfff8000000000000ULL,+ 0ULL,+ 0ULL,+ 0ULL+ },+ {+ 0x0000000041400000ULL,+ 0x1968000000000000ULL,+ -1ULL,+ -1ULL,+ -1ULL+ }+#endif+ },+ { NULL, TILEGX_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } },+#ifndef DISASM_ONLY+ { 0, }, { 0, }+#endif+ }+};++#define BITFIELD(start, size) ((start) | (((1 << (size)) - 1) << 6))+#define CHILD(array_index) (TILEGX_OPC_NONE + (array_index))++static const unsigned short decode_X0_fsm[936] =+{+ BITFIELD(22, 9) /* index 0 */,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BFEXTS,+ TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTU,+ TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFINS,+ TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_MM,+ TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(528), CHILD(578),+ CHILD(583), CHILD(588), CHILD(593), CHILD(598), TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, CHILD(603), CHILD(620), CHILD(637), CHILD(654), CHILD(671),+ CHILD(703), CHILD(797), CHILD(814), CHILD(831), CHILD(848), CHILD(865),+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, CHILD(889), TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906),+ BITFIELD(6, 2) /* index 513 */,+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518),+ BITFIELD(8, 2) /* index 518 */,+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523),+ BITFIELD(10, 2) /* index 523 */,+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI,+ BITFIELD(20, 2) /* index 528 */,+ TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548),+ BITFIELD(6, 2) /* index 533 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538),+ BITFIELD(8, 2) /* index 538 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543),+ BITFIELD(10, 2) /* index 543 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI,+ BITFIELD(0, 2) /* index 548 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553),+ BITFIELD(2, 2) /* index 553 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558),+ BITFIELD(4, 2) /* index 558 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563),+ BITFIELD(6, 2) /* index 563 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568),+ BITFIELD(8, 2) /* index 568 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573),+ BITFIELD(10, 2) /* index 573 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO,+ BITFIELD(20, 2) /* index 578 */,+ TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, TILEGX_OPC_ORI,+ BITFIELD(20, 2) /* index 583 */,+ TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI, TILEGX_OPC_V1CMPLTSI,+ TILEGX_OPC_V1CMPLTUI,+ BITFIELD(20, 2) /* index 588 */,+ TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI, TILEGX_OPC_V2ADDI,+ TILEGX_OPC_V2CMPEQI,+ BITFIELD(20, 2) /* index 593 */,+ TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI, TILEGX_OPC_V2MAXSI,+ TILEGX_OPC_V2MINSI,+ BITFIELD(20, 2) /* index 598 */,+ TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(18, 4) /* index 603 */,+ TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD,+ TILEGX_OPC_AND, TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_CMPEQ,+ TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU,+ TILEGX_OPC_CMPNE, TILEGX_OPC_CMULAF, TILEGX_OPC_CMULA, TILEGX_OPC_CMULFR,+ BITFIELD(18, 4) /* index 620 */,+ TILEGX_OPC_CMULF, TILEGX_OPC_CMULHR, TILEGX_OPC_CMULH, TILEGX_OPC_CMUL,+ TILEGX_OPC_CRC32_32, TILEGX_OPC_CRC32_8, TILEGX_OPC_DBLALIGN2,+ TILEGX_OPC_DBLALIGN4, TILEGX_OPC_DBLALIGN6, TILEGX_OPC_DBLALIGN,+ TILEGX_OPC_FDOUBLE_ADDSUB, TILEGX_OPC_FDOUBLE_ADD_FLAGS,+ TILEGX_OPC_FDOUBLE_MUL_FLAGS, TILEGX_OPC_FDOUBLE_PACK1,+ TILEGX_OPC_FDOUBLE_PACK2, TILEGX_OPC_FDOUBLE_SUB_FLAGS,+ BITFIELD(18, 4) /* index 637 */,+ TILEGX_OPC_FDOUBLE_UNPACK_MAX, TILEGX_OPC_FDOUBLE_UNPACK_MIN,+ TILEGX_OPC_FSINGLE_ADD1, TILEGX_OPC_FSINGLE_ADDSUB2,+ TILEGX_OPC_FSINGLE_MUL1, TILEGX_OPC_FSINGLE_MUL2, TILEGX_OPC_FSINGLE_PACK2,+ TILEGX_OPC_FSINGLE_SUB1, TILEGX_OPC_MNZ, TILEGX_OPC_MULAX,+ TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HS_HU, TILEGX_OPC_MULA_HS_LS,+ TILEGX_OPC_MULA_HS_LU, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_HU_LS,+ BITFIELD(18, 4) /* index 654 */,+ TILEGX_OPC_MULA_HU_LU, TILEGX_OPC_MULA_LS_LS, TILEGX_OPC_MULA_LS_LU,+ TILEGX_OPC_MULA_LU_LU, TILEGX_OPC_MULX, TILEGX_OPC_MUL_HS_HS,+ TILEGX_OPC_MUL_HS_HU, TILEGX_OPC_MUL_HS_LS, TILEGX_OPC_MUL_HS_LU,+ TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_HU_LS, TILEGX_OPC_MUL_HU_LU,+ TILEGX_OPC_MUL_LS_LS, TILEGX_OPC_MUL_LS_LU, TILEGX_OPC_MUL_LU_LU,+ TILEGX_OPC_MZ,+ BITFIELD(18, 4) /* index 671 */,+ TILEGX_OPC_NOR, CHILD(688), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX,+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD,+ TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL,+ TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_SHUFFLEBYTES,+ TILEGX_OPC_SUBXSC,+ BITFIELD(12, 2) /* index 688 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(693),+ BITFIELD(14, 2) /* index 693 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(698),+ BITFIELD(16, 2) /* index 698 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE,+ BITFIELD(18, 4) /* index 703 */,+ TILEGX_OPC_SUBX, TILEGX_OPC_SUB, CHILD(720), TILEGX_OPC_V1ADDUC,+ TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADIFFU, TILEGX_OPC_V1AVGU,+ TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU,+ TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE,+ TILEGX_OPC_V1DDOTPUSA, TILEGX_OPC_V1DDOTPUS, TILEGX_OPC_V1DOTPA,+ BITFIELD(12, 4) /* index 720 */,+ TILEGX_OPC_NONE, CHILD(737), CHILD(742), CHILD(747), CHILD(752), CHILD(757),+ CHILD(762), CHILD(767), CHILD(772), CHILD(777), CHILD(782), CHILD(787),+ CHILD(792), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 737 */,+ TILEGX_OPC_CLZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 742 */,+ TILEGX_OPC_CTZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 747 */,+ TILEGX_OPC_FNOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 752 */,+ TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 757 */,+ TILEGX_OPC_NOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 762 */,+ TILEGX_OPC_PCNT, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 767 */,+ TILEGX_OPC_REVBITS, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 772 */,+ TILEGX_OPC_REVBYTES, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 777 */,+ TILEGX_OPC_TBLIDXB0, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 782 */,+ TILEGX_OPC_TBLIDXB1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 787 */,+ TILEGX_OPC_TBLIDXB2, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(16, 2) /* index 792 */,+ TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(18, 4) /* index 797 */,+ TILEGX_OPC_V1DOTPUSA, TILEGX_OPC_V1DOTPUS, TILEGX_OPC_V1DOTP,+ TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1MAXU,+ TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MULTU, TILEGX_OPC_V1MULUS,+ TILEGX_OPC_V1MULU, TILEGX_OPC_V1MZ, TILEGX_OPC_V1SADAU, TILEGX_OPC_V1SADU,+ TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS,+ BITFIELD(18, 4) /* index 814 */,+ TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC, TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC,+ TILEGX_OPC_V2ADD, TILEGX_OPC_V2ADIFFS, TILEGX_OPC_V2AVGS,+ TILEGX_OPC_V2CMPEQ, TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU,+ TILEGX_OPC_V2CMPLTS, TILEGX_OPC_V2CMPLTU, TILEGX_OPC_V2CMPNE,+ TILEGX_OPC_V2DOTPA, TILEGX_OPC_V2DOTP, TILEGX_OPC_V2INT_H,+ BITFIELD(18, 4) /* index 831 */,+ TILEGX_OPC_V2INT_L, TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ,+ TILEGX_OPC_V2MULFSC, TILEGX_OPC_V2MULS, TILEGX_OPC_V2MULTS, TILEGX_OPC_V2MZ,+ TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC,+ TILEGX_OPC_V2SADAS, TILEGX_OPC_V2SADAU, TILEGX_OPC_V2SADS,+ TILEGX_OPC_V2SADU, TILEGX_OPC_V2SHLSC,+ BITFIELD(18, 4) /* index 848 */,+ TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU, TILEGX_OPC_V2SUBSC,+ TILEGX_OPC_V2SUB, TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H,+ TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC,+ TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC,+ TILEGX_OPC_V4SUB,+ BITFIELD(18, 3) /* index 865 */,+ CHILD(874), CHILD(877), CHILD(880), CHILD(883), CHILD(886), TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(21, 1) /* index 874 */,+ TILEGX_OPC_XOR, TILEGX_OPC_NONE,+ BITFIELD(21, 1) /* index 877 */,+ TILEGX_OPC_V1DDOTPUA, TILEGX_OPC_NONE,+ BITFIELD(21, 1) /* index 880 */,+ TILEGX_OPC_V1DDOTPU, TILEGX_OPC_NONE,+ BITFIELD(21, 1) /* index 883 */,+ TILEGX_OPC_V1DOTPUA, TILEGX_OPC_NONE,+ BITFIELD(21, 1) /* index 886 */,+ TILEGX_OPC_V1DOTPU, TILEGX_OPC_NONE,+ BITFIELD(18, 4) /* index 889 */,+ TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI,+ TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI,+ TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI,+ TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE,+ BITFIELD(0, 2) /* index 906 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ CHILD(911),+ BITFIELD(2, 2) /* index 911 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ CHILD(916),+ BITFIELD(4, 2) /* index 916 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ CHILD(921),+ BITFIELD(6, 2) /* index 921 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ CHILD(926),+ BITFIELD(8, 2) /* index 926 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ CHILD(931),+ BITFIELD(10, 2) /* index 931 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ TILEGX_OPC_INFOL,+};++static const unsigned short decode_X1_fsm[1266] =+{+ BITFIELD(53, 9) /* index 0 */,+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513),+ CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI,+ TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BEQZT,+ TILEGX_OPC_BEQZT, TILEGX_OPC_BEQZ, TILEGX_OPC_BEQZ, TILEGX_OPC_BGEZT,+ TILEGX_OPC_BGEZT, TILEGX_OPC_BGEZ, TILEGX_OPC_BGEZ, TILEGX_OPC_BGTZT,+ TILEGX_OPC_BGTZT, TILEGX_OPC_BGTZ, TILEGX_OPC_BGTZ, TILEGX_OPC_BLBCT,+ TILEGX_OPC_BLBCT, TILEGX_OPC_BLBC, TILEGX_OPC_BLBC, TILEGX_OPC_BLBST,+ TILEGX_OPC_BLBST, TILEGX_OPC_BLBS, TILEGX_OPC_BLBS, TILEGX_OPC_BLEZT,+ TILEGX_OPC_BLEZT, TILEGX_OPC_BLEZ, TILEGX_OPC_BLEZ, TILEGX_OPC_BLTZT,+ TILEGX_OPC_BLTZT, TILEGX_OPC_BLTZ, TILEGX_OPC_BLTZ, TILEGX_OPC_BNEZT,+ TILEGX_OPC_BNEZT, TILEGX_OPC_BNEZ, TILEGX_OPC_BNEZ, CHILD(528), CHILD(578),+ CHILD(598), CHILD(703), CHILD(723), CHILD(728), CHILD(753), CHILD(758),+ CHILD(763), CHILD(768), CHILD(773), CHILD(778), TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_JAL,+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL,+ TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_J, TILEGX_OPC_J,+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,+ TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J,+ CHILD(783), CHILD(800), CHILD(832), CHILD(849), CHILD(1168), CHILD(1185),+ CHILD(1202), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1219), TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236),+ CHILD(1236),+ BITFIELD(37, 2) /* index 513 */,+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518),+ BITFIELD(39, 2) /* index 518 */,+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523),+ BITFIELD(41, 2) /* index 523 */,+ TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI,+ BITFIELD(51, 2) /* index 528 */,+ TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548),+ BITFIELD(37, 2) /* index 533 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538),+ BITFIELD(39, 2) /* index 538 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543),+ BITFIELD(41, 2) /* index 543 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI,+ BITFIELD(31, 2) /* index 548 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553),+ BITFIELD(33, 2) /* index 553 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558),+ BITFIELD(35, 2) /* index 558 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563),+ BITFIELD(37, 2) /* index 563 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568),+ BITFIELD(39, 2) /* index 568 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573),+ BITFIELD(41, 2) /* index 573 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO,+ BITFIELD(51, 2) /* index 578 */,+ TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, CHILD(583),+ BITFIELD(31, 2) /* index 583 */,+ TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(588),+ BITFIELD(33, 2) /* index 588 */,+ TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(593),+ BITFIELD(35, 2) /* index 593 */,+ TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD,+ TILEGX_OPC_PREFETCH_ADD_L1_FAULT,+ BITFIELD(51, 2) /* index 598 */,+ CHILD(603), CHILD(618), CHILD(633), CHILD(648),+ BITFIELD(31, 2) /* index 603 */,+ TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(608),+ BITFIELD(33, 2) /* index 608 */,+ TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(613),+ BITFIELD(35, 2) /* index 613 */,+ TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD,+ TILEGX_OPC_PREFETCH_ADD_L1,+ BITFIELD(31, 2) /* index 618 */,+ TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(623),+ BITFIELD(33, 2) /* index 623 */,+ TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(628),+ BITFIELD(35, 2) /* index 628 */,+ TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD,+ TILEGX_OPC_PREFETCH_ADD_L2_FAULT,+ BITFIELD(31, 2) /* index 633 */,+ TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(638),+ BITFIELD(33, 2) /* index 638 */,+ TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(643),+ BITFIELD(35, 2) /* index 643 */,+ TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD,+ TILEGX_OPC_PREFETCH_ADD_L2,+ BITFIELD(31, 2) /* index 648 */,+ CHILD(653), CHILD(653), CHILD(653), CHILD(673),+ BITFIELD(43, 2) /* index 653 */,+ CHILD(658), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD,+ BITFIELD(45, 2) /* index 658 */,+ CHILD(663), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD,+ BITFIELD(47, 2) /* index 663 */,+ CHILD(668), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD,+ BITFIELD(49, 2) /* index 668 */,+ TILEGX_OPC_LD4S_TLS, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD,+ TILEGX_OPC_LD4S_ADD,+ BITFIELD(33, 2) /* index 673 */,+ CHILD(653), CHILD(653), CHILD(653), CHILD(678),+ BITFIELD(35, 2) /* index 678 */,+ CHILD(653), CHILD(653), CHILD(653), CHILD(683),+ BITFIELD(43, 2) /* index 683 */,+ CHILD(688), TILEGX_OPC_PREFETCH_ADD_L3_FAULT,+ TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT,+ BITFIELD(45, 2) /* index 688 */,+ CHILD(693), TILEGX_OPC_PREFETCH_ADD_L3_FAULT,+ TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT,+ BITFIELD(47, 2) /* index 693 */,+ CHILD(698), TILEGX_OPC_PREFETCH_ADD_L3_FAULT,+ TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT,+ BITFIELD(49, 2) /* index 698 */,+ TILEGX_OPC_LD4S_TLS, TILEGX_OPC_PREFETCH_ADD_L3_FAULT,+ TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT,+ BITFIELD(51, 2) /* index 703 */,+ CHILD(708), TILEGX_OPC_LDNT1S_ADD, TILEGX_OPC_LDNT1U_ADD,+ TILEGX_OPC_LDNT2S_ADD,+ BITFIELD(31, 2) /* index 708 */,+ TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(713),+ BITFIELD(33, 2) /* index 713 */,+ TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(718),+ BITFIELD(35, 2) /* index 718 */,+ TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD,+ TILEGX_OPC_PREFETCH_ADD_L3,+ BITFIELD(51, 2) /* index 723 */,+ TILEGX_OPC_LDNT2U_ADD, TILEGX_OPC_LDNT4S_ADD, TILEGX_OPC_LDNT4U_ADD,+ TILEGX_OPC_LDNT_ADD,+ BITFIELD(51, 2) /* index 728 */,+ CHILD(733), TILEGX_OPC_LDNA_ADD, TILEGX_OPC_MFSPR, TILEGX_OPC_MTSPR,+ BITFIELD(43, 2) /* index 733 */,+ CHILD(738), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD,+ BITFIELD(45, 2) /* index 738 */,+ CHILD(743), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD,+ BITFIELD(47, 2) /* index 743 */,+ CHILD(748), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD,+ BITFIELD(49, 2) /* index 748 */,+ TILEGX_OPC_LD_TLS, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD,+ BITFIELD(51, 2) /* index 753 */,+ TILEGX_OPC_ORI, TILEGX_OPC_ST1_ADD, TILEGX_OPC_ST2_ADD, TILEGX_OPC_ST4_ADD,+ BITFIELD(51, 2) /* index 758 */,+ TILEGX_OPC_STNT1_ADD, TILEGX_OPC_STNT2_ADD, TILEGX_OPC_STNT4_ADD,+ TILEGX_OPC_STNT_ADD,+ BITFIELD(51, 2) /* index 763 */,+ TILEGX_OPC_ST_ADD, TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI,+ TILEGX_OPC_V1CMPLTSI,+ BITFIELD(51, 2) /* index 768 */,+ TILEGX_OPC_V1CMPLTUI, TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI,+ TILEGX_OPC_V2ADDI,+ BITFIELD(51, 2) /* index 773 */,+ TILEGX_OPC_V2CMPEQI, TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI,+ TILEGX_OPC_V2MAXSI,+ BITFIELD(51, 2) /* index 778 */,+ TILEGX_OPC_V2MINSI, TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(49, 4) /* index 783 */,+ TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD,+ TILEGX_OPC_AND, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPEXCH4, TILEGX_OPC_CMPEXCH,+ TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU,+ TILEGX_OPC_CMPNE, TILEGX_OPC_DBLALIGN2, TILEGX_OPC_DBLALIGN4,+ TILEGX_OPC_DBLALIGN6,+ BITFIELD(49, 4) /* index 800 */,+ TILEGX_OPC_EXCH4, TILEGX_OPC_EXCH, TILEGX_OPC_FETCHADD4,+ TILEGX_OPC_FETCHADDGEZ4, TILEGX_OPC_FETCHADDGEZ, TILEGX_OPC_FETCHADD,+ TILEGX_OPC_FETCHAND4, TILEGX_OPC_FETCHAND, TILEGX_OPC_FETCHOR4,+ TILEGX_OPC_FETCHOR, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, TILEGX_OPC_NOR,+ CHILD(817), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX,+ BITFIELD(43, 2) /* index 817 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(822),+ BITFIELD(45, 2) /* index 822 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(827),+ BITFIELD(47, 2) /* index 827 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE,+ BITFIELD(49, 4) /* index 832 */,+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD,+ TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL,+ TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_ST1,+ TILEGX_OPC_ST2, TILEGX_OPC_ST4, TILEGX_OPC_STNT1, TILEGX_OPC_STNT2,+ TILEGX_OPC_STNT4,+ BITFIELD(46, 7) /* index 849 */,+ TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT,+ TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT,+ TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST,+ TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_SUBXSC,+ TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC,+ TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBX,+ TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX,+ TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUB,+ TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB,+ TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, CHILD(978), CHILD(987),+ CHILD(1066), CHILD(1150), CHILD(1159), TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC,+ TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC,+ TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD,+ TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD,+ TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ,+ TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ,+ TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ,+ TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES,+ TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES,+ TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU,+ TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU,+ TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU,+ TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS,+ TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS,+ TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS,+ TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU,+ TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU,+ TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE,+ TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE,+ TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE,+ TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H,+ TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H,+ TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H,+ TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L,+ TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L,+ TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L,+ BITFIELD(43, 3) /* index 978 */,+ TILEGX_OPC_NONE, TILEGX_OPC_DRAIN, TILEGX_OPC_DTLBPR, TILEGX_OPC_FINV,+ TILEGX_OPC_FLUSHWB, TILEGX_OPC_FLUSH, TILEGX_OPC_FNOP, TILEGX_OPC_ICOH,+ BITFIELD(43, 3) /* index 987 */,+ CHILD(996), TILEGX_OPC_INV, TILEGX_OPC_IRET, TILEGX_OPC_JALRP,+ TILEGX_OPC_JALR, TILEGX_OPC_JRP, TILEGX_OPC_JR, CHILD(1051),+ BITFIELD(31, 2) /* index 996 */,+ CHILD(1001), CHILD(1026), TILEGX_OPC_ILL, TILEGX_OPC_ILL,+ BITFIELD(33, 2) /* index 1001 */,+ TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(1006),+ BITFIELD(35, 2) /* index 1006 */,+ TILEGX_OPC_ILL, CHILD(1011), TILEGX_OPC_ILL, TILEGX_OPC_ILL,+ BITFIELD(37, 2) /* index 1011 */,+ TILEGX_OPC_ILL, CHILD(1016), TILEGX_OPC_ILL, TILEGX_OPC_ILL,+ BITFIELD(39, 2) /* index 1016 */,+ TILEGX_OPC_ILL, CHILD(1021), TILEGX_OPC_ILL, TILEGX_OPC_ILL,+ BITFIELD(41, 2) /* index 1021 */,+ TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_BPT, TILEGX_OPC_ILL,+ BITFIELD(33, 2) /* index 1026 */,+ TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(1031),+ BITFIELD(35, 2) /* index 1031 */,+ TILEGX_OPC_ILL, CHILD(1036), TILEGX_OPC_ILL, TILEGX_OPC_ILL,+ BITFIELD(37, 2) /* index 1036 */,+ TILEGX_OPC_ILL, CHILD(1041), TILEGX_OPC_ILL, TILEGX_OPC_ILL,+ BITFIELD(39, 2) /* index 1041 */,+ TILEGX_OPC_ILL, CHILD(1046), TILEGX_OPC_ILL, TILEGX_OPC_ILL,+ BITFIELD(41, 2) /* index 1046 */,+ TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_RAISE, TILEGX_OPC_ILL,+ BITFIELD(31, 2) /* index 1051 */,+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(1056),+ BITFIELD(33, 2) /* index 1056 */,+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(1061),+ BITFIELD(35, 2) /* index 1061 */,+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S,+ TILEGX_OPC_PREFETCH_L1_FAULT,+ BITFIELD(43, 3) /* index 1066 */,+ CHILD(1075), CHILD(1090), CHILD(1105), CHILD(1120), CHILD(1135),+ TILEGX_OPC_LDNA, TILEGX_OPC_LDNT1S, TILEGX_OPC_LDNT1U,+ BITFIELD(31, 2) /* index 1075 */,+ TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1080),+ BITFIELD(33, 2) /* index 1080 */,+ TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1085),+ BITFIELD(35, 2) /* index 1085 */,+ TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH,+ BITFIELD(31, 2) /* index 1090 */,+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1095),+ BITFIELD(33, 2) /* index 1095 */,+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1100),+ BITFIELD(35, 2) /* index 1100 */,+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S,+ TILEGX_OPC_PREFETCH_L2_FAULT,+ BITFIELD(31, 2) /* index 1105 */,+ TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1110),+ BITFIELD(33, 2) /* index 1110 */,+ TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1115),+ BITFIELD(35, 2) /* index 1115 */,+ TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2,+ BITFIELD(31, 2) /* index 1120 */,+ TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1125),+ BITFIELD(33, 2) /* index 1125 */,+ TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1130),+ BITFIELD(35, 2) /* index 1130 */,+ TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S,+ TILEGX_OPC_PREFETCH_L3_FAULT,+ BITFIELD(31, 2) /* index 1135 */,+ TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1140),+ BITFIELD(33, 2) /* index 1140 */,+ TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1145),+ BITFIELD(35, 2) /* index 1145 */,+ TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3,+ BITFIELD(43, 3) /* index 1150 */,+ TILEGX_OPC_LDNT2S, TILEGX_OPC_LDNT2U, TILEGX_OPC_LDNT4S, TILEGX_OPC_LDNT4U,+ TILEGX_OPC_LDNT, TILEGX_OPC_LD, TILEGX_OPC_LNK, TILEGX_OPC_MF,+ BITFIELD(43, 3) /* index 1159 */,+ TILEGX_OPC_NAP, TILEGX_OPC_NOP, TILEGX_OPC_SWINT0, TILEGX_OPC_SWINT1,+ TILEGX_OPC_SWINT2, TILEGX_OPC_SWINT3, TILEGX_OPC_WH64, TILEGX_OPC_NONE,+ BITFIELD(49, 4) /* index 1168 */,+ TILEGX_OPC_V1MAXU, TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MZ,+ TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS, TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC,+ TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC, TILEGX_OPC_V2ADD, TILEGX_OPC_V2CMPEQ,+ TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, TILEGX_OPC_V2CMPLTS,+ TILEGX_OPC_V2CMPLTU,+ BITFIELD(49, 4) /* index 1185 */,+ TILEGX_OPC_V2CMPNE, TILEGX_OPC_V2INT_H, TILEGX_OPC_V2INT_L,+ TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ, TILEGX_OPC_V2MZ,+ TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC,+ TILEGX_OPC_V2SHLSC, TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU,+ TILEGX_OPC_V2SUBSC, TILEGX_OPC_V2SUB,+ BITFIELD(49, 4) /* index 1202 */,+ TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H,+ TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC,+ TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC,+ TILEGX_OPC_V4SUB, TILEGX_OPC_XOR, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(49, 4) /* index 1219 */,+ TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI,+ TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI,+ TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI,+ TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE,+ BITFIELD(31, 2) /* index 1236 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ CHILD(1241),+ BITFIELD(33, 2) /* index 1241 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ CHILD(1246),+ BITFIELD(35, 2) /* index 1246 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ CHILD(1251),+ BITFIELD(37, 2) /* index 1251 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ CHILD(1256),+ BITFIELD(39, 2) /* index 1256 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ CHILD(1261),+ BITFIELD(41, 2) /* index 1261 */,+ TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI,+ TILEGX_OPC_INFOL,+};++static const unsigned short decode_Y0_fsm[178] =+{+ BITFIELD(27, 4) /* index 0 */,+ CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI,+ TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(118), CHILD(123),+ CHILD(128), CHILD(133), CHILD(153), CHILD(158), CHILD(163), CHILD(168),+ CHILD(173),+ BITFIELD(6, 2) /* index 17 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22),+ BITFIELD(8, 2) /* index 22 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27),+ BITFIELD(10, 2) /* index 27 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI,+ BITFIELD(0, 2) /* index 32 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37),+ BITFIELD(2, 2) /* index 37 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42),+ BITFIELD(4, 2) /* index 42 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47),+ BITFIELD(6, 2) /* index 47 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52),+ BITFIELD(8, 2) /* index 52 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57),+ BITFIELD(10, 2) /* index 57 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO,+ BITFIELD(18, 2) /* index 62 */,+ TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB,+ BITFIELD(15, 5) /* index 67 */,+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD,+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD,+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD,+ TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD,+ TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD,+ TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD,+ TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD,+ TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(100),+ CHILD(109), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(12, 3) /* index 100 */,+ TILEGX_OPC_NONE, TILEGX_OPC_CLZ, TILEGX_OPC_CTZ, TILEGX_OPC_FNOP,+ TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NOP, TILEGX_OPC_PCNT,+ TILEGX_OPC_REVBITS,+ BITFIELD(12, 3) /* index 109 */,+ TILEGX_OPC_REVBYTES, TILEGX_OPC_TBLIDXB0, TILEGX_OPC_TBLIDXB1,+ TILEGX_OPC_TBLIDXB2, TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ TILEGX_OPC_NONE,+ BITFIELD(18, 2) /* index 118 */,+ TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU,+ BITFIELD(18, 2) /* index 123 */,+ TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE, TILEGX_OPC_MULAX, TILEGX_OPC_MULX,+ BITFIELD(18, 2) /* index 128 */,+ TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_MNZ, TILEGX_OPC_MZ,+ BITFIELD(18, 2) /* index 133 */,+ TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(138), TILEGX_OPC_XOR,+ BITFIELD(12, 2) /* index 138 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(143),+ BITFIELD(14, 2) /* index 143 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(148),+ BITFIELD(16, 2) /* index 148 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE,+ BITFIELD(18, 2) /* index 153 */,+ TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU,+ BITFIELD(18, 2) /* index 158 */,+ TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX,+ TILEGX_OPC_SHL3ADDX,+ BITFIELD(18, 2) /* index 163 */,+ TILEGX_OPC_MUL_HS_HS, TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_LS_LS,+ TILEGX_OPC_MUL_LU_LU,+ BITFIELD(18, 2) /* index 168 */,+ TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_LS_LS,+ TILEGX_OPC_MULA_LU_LU,+ BITFIELD(18, 2) /* index 173 */,+ TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI,+};++static const unsigned short decode_Y1_fsm[167] =+{+ BITFIELD(58, 4) /* index 0 */,+ TILEGX_OPC_NONE, CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI,+ TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(117), CHILD(122),+ CHILD(127), CHILD(132), CHILD(152), CHILD(157), CHILD(162), TILEGX_OPC_NONE,+ BITFIELD(37, 2) /* index 17 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22),+ BITFIELD(39, 2) /* index 22 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27),+ BITFIELD(41, 2) /* index 27 */,+ TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI,+ BITFIELD(31, 2) /* index 32 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37),+ BITFIELD(33, 2) /* index 37 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42),+ BITFIELD(35, 2) /* index 42 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47),+ BITFIELD(37, 2) /* index 47 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52),+ BITFIELD(39, 2) /* index 52 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57),+ BITFIELD(41, 2) /* index 57 */,+ TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO,+ BITFIELD(49, 2) /* index 62 */,+ TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB,+ BITFIELD(47, 4) /* index 67 */,+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD,+ TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD,+ TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD,+ TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(84),+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE,+ BITFIELD(43, 3) /* index 84 */,+ CHILD(93), CHILD(96), CHILD(99), CHILD(102), CHILD(105), CHILD(108),+ CHILD(111), CHILD(114),+ BITFIELD(46, 1) /* index 93 */,+ TILEGX_OPC_NONE, TILEGX_OPC_FNOP,+ BITFIELD(46, 1) /* index 96 */,+ TILEGX_OPC_NONE, TILEGX_OPC_ILL,+ BITFIELD(46, 1) /* index 99 */,+ TILEGX_OPC_NONE, TILEGX_OPC_JALRP,+ BITFIELD(46, 1) /* index 102 */,+ TILEGX_OPC_NONE, TILEGX_OPC_JALR,+ BITFIELD(46, 1) /* index 105 */,+ TILEGX_OPC_NONE, TILEGX_OPC_JRP,+ BITFIELD(46, 1) /* index 108 */,+ TILEGX_OPC_NONE, TILEGX_OPC_JR,+ BITFIELD(46, 1) /* index 111 */,+ TILEGX_OPC_NONE, TILEGX_OPC_LNK,+ BITFIELD(46, 1) /* index 114 */,+ TILEGX_OPC_NONE, TILEGX_OPC_NOP,+ BITFIELD(49, 2) /* index 117 */,+ TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU,+ BITFIELD(49, 2) /* index 122 */,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE,+ BITFIELD(49, 2) /* index 127 */,+ TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_MNZ, TILEGX_OPC_MZ,+ BITFIELD(49, 2) /* index 132 */,+ TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(137), TILEGX_OPC_XOR,+ BITFIELD(43, 2) /* index 137 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(142),+ BITFIELD(45, 2) /* index 142 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(147),+ BITFIELD(47, 2) /* index 147 */,+ TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE,+ BITFIELD(49, 2) /* index 152 */,+ TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU,+ BITFIELD(49, 2) /* index 157 */,+ TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX,+ TILEGX_OPC_SHL3ADDX,+ BITFIELD(49, 2) /* index 162 */,+ TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI,+};++static const unsigned short decode_Y2_fsm[118] =+{+ BITFIELD(62, 2) /* index 0 */,+ TILEGX_OPC_NONE, CHILD(5), CHILD(66), CHILD(109),+ BITFIELD(55, 3) /* index 5 */,+ CHILD(14), CHILD(14), CHILD(14), CHILD(17), CHILD(40), CHILD(40), CHILD(40),+ CHILD(43),+ BITFIELD(26, 1) /* index 14 */,+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1U,+ BITFIELD(26, 1) /* index 17 */,+ CHILD(20), CHILD(30),+ BITFIELD(51, 2) /* index 20 */,+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(25),+ BITFIELD(53, 2) /* index 25 */,+ TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S,+ TILEGX_OPC_PREFETCH_L1_FAULT,+ BITFIELD(51, 2) /* index 30 */,+ TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(35),+ BITFIELD(53, 2) /* index 35 */,+ TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH,+ BITFIELD(26, 1) /* index 40 */,+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2U,+ BITFIELD(26, 1) /* index 43 */,+ CHILD(46), CHILD(56),+ BITFIELD(51, 2) /* index 46 */,+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(51),+ BITFIELD(53, 2) /* index 51 */,+ TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S,+ TILEGX_OPC_PREFETCH_L2_FAULT,+ BITFIELD(51, 2) /* index 56 */,+ TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(61),+ BITFIELD(53, 2) /* index 61 */,+ TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2,+ BITFIELD(56, 2) /* index 66 */,+ CHILD(71), CHILD(74), CHILD(90), CHILD(93),+ BITFIELD(26, 1) /* index 71 */,+ TILEGX_OPC_NONE, TILEGX_OPC_LD4S,+ BITFIELD(26, 1) /* index 74 */,+ TILEGX_OPC_NONE, CHILD(77),+ BITFIELD(51, 2) /* index 77 */,+ TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(82),+ BITFIELD(53, 2) /* index 82 */,+ TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(87),+ BITFIELD(55, 1) /* index 87 */,+ TILEGX_OPC_LD4S, TILEGX_OPC_PREFETCH_L3_FAULT,+ BITFIELD(26, 1) /* index 90 */,+ TILEGX_OPC_LD4U, TILEGX_OPC_LD,+ BITFIELD(26, 1) /* index 93 */,+ CHILD(96), TILEGX_OPC_LD,+ BITFIELD(51, 2) /* index 96 */,+ TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(101),+ BITFIELD(53, 2) /* index 101 */,+ TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(106),+ BITFIELD(55, 1) /* index 106 */,+ TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3,+ BITFIELD(26, 1) /* index 109 */,+ CHILD(112), CHILD(115),+ BITFIELD(57, 1) /* index 112 */,+ TILEGX_OPC_ST1, TILEGX_OPC_ST4,+ BITFIELD(57, 1) /* index 115 */,+ TILEGX_OPC_ST2, TILEGX_OPC_ST,+};++#undef BITFIELD+#undef CHILD++const unsigned short * const+tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS] =+{+ decode_X0_fsm,+ decode_X1_fsm,+ decode_Y0_fsm,+ decode_Y1_fsm,+ decode_Y2_fsm+};++const struct tilegx_operand tilegx_operands[35] =+{+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X0),+ 8, 1, 0, 0, 0, 0,+ create_Imm8_X0, get_Imm8_X0+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X1),+ 8, 1, 0, 0, 0, 0,+ create_Imm8_X1, get_Imm8_X1+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y0),+ 8, 1, 0, 0, 0, 0,+ create_Imm8_Y0, get_Imm8_Y0+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y1),+ 8, 1, 0, 0, 0, 0,+ create_Imm8_Y1, get_Imm8_Y1+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X0_HW0_LAST),+ 16, 1, 0, 0, 0, 0,+ create_Imm16_X0, get_Imm16_X0+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X1_HW0_LAST),+ 16, 1, 0, 0, 0, 0,+ create_Imm16_X1, get_Imm16_X1+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 0, 1, 0, 0,+ create_Dest_X1, get_Dest_X1+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 0, 0, 0,+ create_SrcA_X1, get_SrcA_X1+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 0, 1, 0, 0,+ create_Dest_X0, get_Dest_X0+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 0, 0, 0,+ create_SrcA_X0, get_SrcA_X0+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 0, 1, 0, 0,+ create_Dest_Y0, get_Dest_Y0+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 0, 0, 0,+ create_SrcA_Y0, get_SrcA_Y0+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 0, 1, 0, 0,+ create_Dest_Y1, get_Dest_Y1+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 0, 0, 0,+ create_SrcA_Y1, get_SrcA_Y1+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 0, 0, 0,+ create_SrcA_Y2, get_SrcA_Y2+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 1, 0, 0,+ create_SrcA_X1, get_SrcA_X1+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 0, 0, 0,+ create_SrcB_X0, get_SrcB_X0+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 0, 0, 0,+ create_SrcB_X1, get_SrcB_X1+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 0, 0, 0,+ create_SrcB_Y0, get_SrcB_Y0+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 0, 0, 0,+ create_SrcB_Y1, get_SrcB_Y1+ },+ {+ TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_BROFF_X1),+ 17, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,+ create_BrOff_X1, get_BrOff_X1+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMSTART_X0),+ 6, 0, 0, 0, 0, 0,+ create_BFStart_X0, get_BFStart_X0+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMEND_X0),+ 6, 0, 0, 0, 0, 0,+ create_BFEnd_X0, get_BFEnd_X0+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 1, 0, 0,+ create_Dest_X0, get_Dest_X0+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 1, 0, 0,+ create_Dest_Y0, get_Dest_Y0+ },+ {+ TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_JUMPOFF_X1),+ 27, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,+ create_JumpOff_X1, get_JumpOff_X1+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 0, 1, 0, 0,+ create_SrcBDest_Y2, get_SrcBDest_Y2+ },+ {+ TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MF_IMM14_X1),+ 14, 0, 0, 0, 0, 0,+ create_MF_Imm14_X1, get_MF_Imm14_X1+ },+ {+ TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MT_IMM14_X1),+ 14, 0, 0, 0, 0, 0,+ create_MT_Imm14_X1, get_MT_Imm14_X1+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X0),+ 6, 0, 0, 0, 0, 0,+ create_ShAmt_X0, get_ShAmt_X0+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X1),+ 6, 0, 0, 0, 0, 0,+ create_ShAmt_X1, get_ShAmt_X1+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y0),+ 6, 0, 0, 0, 0, 0,+ create_ShAmt_Y0, get_ShAmt_Y0+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y1),+ 6, 0, 0, 0, 0, 0,+ create_ShAmt_Y1, get_ShAmt_Y1+ },+ {+ TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE),+ 6, 0, 1, 0, 0, 0,+ create_SrcBDest_Y2, get_SrcBDest_Y2+ },+ {+ TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_DEST_IMM8_X1),+ 8, 1, 0, 0, 0, 0,+ create_Dest_Imm8_X1, get_Dest_Imm8_X1+ }+};++/* Given a set of bundle bits and a specific pipe, returns which+ * instruction the bundle contains in that pipe.+ */+const struct tilegx_opcode *+find_opcode(tilegx_bundle_bits bits, tilegx_pipeline pipe)+{+ const unsigned short *table = tilegx_bundle_decoder_fsms[pipe];+ int index = 0;++ while (1)+ {+ unsigned short bitspec = table[index];+ unsigned int bitfield =+ ((unsigned int)(bits >> (bitspec & 63))) & (bitspec >> 6);++ unsigned short next = table[index + 1 + bitfield];+ if (next <= TILEGX_OPC_NONE)+ return &tilegx_opcodes[next];++ index = next - TILEGX_OPC_NONE;+ }+}++int+parse_insn_tilegx(tilegx_bundle_bits bits,+ unsigned long long pc,+ struct tilegx_decoded_instruction+ decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE])+{+ int num_instructions = 0;+ int pipe;++ int min_pipe, max_pipe;+ if ((bits & TILEGX_BUNDLE_MODE_MASK) == 0)+ {+ min_pipe = TILEGX_PIPELINE_X0;+ max_pipe = TILEGX_PIPELINE_X1;+ }+ else+ {+ min_pipe = TILEGX_PIPELINE_Y0;+ max_pipe = TILEGX_PIPELINE_Y2;+ }++ /* For each pipe, find an instruction that fits. */+ for (pipe = min_pipe; pipe <= max_pipe; pipe++)+ {+ const struct tilegx_opcode *opc;+ struct tilegx_decoded_instruction *d;+ int i;++ d = &decoded[num_instructions++];+ opc = find_opcode (bits, (tilegx_pipeline)pipe);+ d->opcode = opc;++ /* Decode each operand, sign extending, etc. as appropriate. */+ for (i = 0; i < opc->num_operands; i++)+ {+ const struct tilegx_operand *op =+ &tilegx_operands[opc->operands[pipe][i]];+ int raw_opval = op->extract (bits);+ long long opval;++ if (op->is_signed)+ {+ /* Sign-extend the operand. */+ int shift = (int)((sizeof(int) * 8) - op->num_bits);+ raw_opval = (raw_opval << shift) >> shift;+ }++ /* Adjust PC-relative scaled branch offsets. */+ if (op->type == TILEGX_OP_TYPE_ADDRESS)+ opval = (raw_opval * TILEGX_BUNDLE_SIZE_IN_BYTES) + pc;+ else+ opval = raw_opval;++ /* Record the final value. */+ d->operands[i] = op;+ d->operand_values[i] = opval;+ }+ }++ return num_instructions;+}++struct tilegx_spr+{+ /* The number */+ int number;++ /* The name */+ const char *name;+};++static int+tilegx_spr_compare (const void *a_ptr, const void *b_ptr)+{+ const struct tilegx_spr *a = (const struct tilegx_spr *) a_ptr;+ const struct tilegx_spr *b = (const struct tilegx_spr *) b_ptr;+ return (a->number - b->number);+}++const struct tilegx_spr tilegx_sprs[] = {+ { 0, "MPL_MEM_ERROR_SET_0" },+ { 1, "MPL_MEM_ERROR_SET_1" },+ { 2, "MPL_MEM_ERROR_SET_2" },+ { 3, "MPL_MEM_ERROR_SET_3" },+ { 4, "MPL_MEM_ERROR" },+ { 5, "MEM_ERROR_CBOX_ADDR" },+ { 6, "MEM_ERROR_CBOX_STATUS" },+ { 7, "MEM_ERROR_ENABLE" },+ { 8, "MEM_ERROR_MBOX_ADDR" },+ { 9, "MEM_ERROR_MBOX_STATUS" },+ { 10, "SBOX_ERROR" },+ { 11, "XDN_DEMUX_ERROR" },+ { 256, "MPL_SINGLE_STEP_3_SET_0" },+ { 257, "MPL_SINGLE_STEP_3_SET_1" },+ { 258, "MPL_SINGLE_STEP_3_SET_2" },+ { 259, "MPL_SINGLE_STEP_3_SET_3" },+ { 260, "MPL_SINGLE_STEP_3" },+ { 261, "SINGLE_STEP_CONTROL_3" },+ { 512, "MPL_SINGLE_STEP_2_SET_0" },+ { 513, "MPL_SINGLE_STEP_2_SET_1" },+ { 514, "MPL_SINGLE_STEP_2_SET_2" },+ { 515, "MPL_SINGLE_STEP_2_SET_3" },+ { 516, "MPL_SINGLE_STEP_2" },+ { 517, "SINGLE_STEP_CONTROL_2" },+ { 768, "MPL_SINGLE_STEP_1_SET_0" },+ { 769, "MPL_SINGLE_STEP_1_SET_1" },+ { 770, "MPL_SINGLE_STEP_1_SET_2" },+ { 771, "MPL_SINGLE_STEP_1_SET_3" },+ { 772, "MPL_SINGLE_STEP_1" },+ { 773, "SINGLE_STEP_CONTROL_1" },+ { 1024, "MPL_SINGLE_STEP_0_SET_0" },+ { 1025, "MPL_SINGLE_STEP_0_SET_1" },+ { 1026, "MPL_SINGLE_STEP_0_SET_2" },+ { 1027, "MPL_SINGLE_STEP_0_SET_3" },+ { 1028, "MPL_SINGLE_STEP_0" },+ { 1029, "SINGLE_STEP_CONTROL_0" },+ { 1280, "MPL_IDN_COMPLETE_SET_0" },+ { 1281, "MPL_IDN_COMPLETE_SET_1" },+ { 1282, "MPL_IDN_COMPLETE_SET_2" },+ { 1283, "MPL_IDN_COMPLETE_SET_3" },+ { 1284, "MPL_IDN_COMPLETE" },+ { 1285, "IDN_COMPLETE_PENDING" },+ { 1536, "MPL_UDN_COMPLETE_SET_0" },+ { 1537, "MPL_UDN_COMPLETE_SET_1" },+ { 1538, "MPL_UDN_COMPLETE_SET_2" },+ { 1539, "MPL_UDN_COMPLETE_SET_3" },+ { 1540, "MPL_UDN_COMPLETE" },+ { 1541, "UDN_COMPLETE_PENDING" },+ { 1792, "MPL_ITLB_MISS_SET_0" },+ { 1793, "MPL_ITLB_MISS_SET_1" },+ { 1794, "MPL_ITLB_MISS_SET_2" },+ { 1795, "MPL_ITLB_MISS_SET_3" },+ { 1796, "MPL_ITLB_MISS" },+ { 1797, "ITLB_TSB_BASE_ADDR_0" },+ { 1798, "ITLB_TSB_BASE_ADDR_1" },+ { 1920, "ITLB_CURRENT_ATTR" },+ { 1921, "ITLB_CURRENT_PA" },+ { 1922, "ITLB_CURRENT_VA" },+ { 1923, "ITLB_INDEX" },+ { 1924, "ITLB_MATCH_0" },+ { 1925, "ITLB_PERF" },+ { 1926, "ITLB_PR" },+ { 1927, "ITLB_TSB_ADDR_0" },+ { 1928, "ITLB_TSB_ADDR_1" },+ { 1929, "ITLB_TSB_FILL_CURRENT_ATTR" },+ { 1930, "ITLB_TSB_FILL_MATCH" },+ { 1931, "NUMBER_ITLB" },+ { 1932, "REPLACEMENT_ITLB" },+ { 1933, "WIRED_ITLB" },+ { 2048, "MPL_ILL_SET_0" },+ { 2049, "MPL_ILL_SET_1" },+ { 2050, "MPL_ILL_SET_2" },+ { 2051, "MPL_ILL_SET_3" },+ { 2052, "MPL_ILL" },+ { 2304, "MPL_GPV_SET_0" },+ { 2305, "MPL_GPV_SET_1" },+ { 2306, "MPL_GPV_SET_2" },+ { 2307, "MPL_GPV_SET_3" },+ { 2308, "MPL_GPV" },+ { 2309, "GPV_REASON" },+ { 2560, "MPL_IDN_ACCESS_SET_0" },+ { 2561, "MPL_IDN_ACCESS_SET_1" },+ { 2562, "MPL_IDN_ACCESS_SET_2" },+ { 2563, "MPL_IDN_ACCESS_SET_3" },+ { 2564, "MPL_IDN_ACCESS" },+ { 2565, "IDN_DEMUX_COUNT_0" },+ { 2566, "IDN_DEMUX_COUNT_1" },+ { 2567, "IDN_FLUSH_EGRESS" },+ { 2568, "IDN_PENDING" },+ { 2569, "IDN_ROUTE_ORDER" },+ { 2570, "IDN_SP_FIFO_CNT" },+ { 2688, "IDN_DATA_AVAIL" },+ { 2816, "MPL_UDN_ACCESS_SET_0" },+ { 2817, "MPL_UDN_ACCESS_SET_1" },+ { 2818, "MPL_UDN_ACCESS_SET_2" },+ { 2819, "MPL_UDN_ACCESS_SET_3" },+ { 2820, "MPL_UDN_ACCESS" },+ { 2821, "UDN_DEMUX_COUNT_0" },+ { 2822, "UDN_DEMUX_COUNT_1" },+ { 2823, "UDN_DEMUX_COUNT_2" },+ { 2824, "UDN_DEMUX_COUNT_3" },+ { 2825, "UDN_FLUSH_EGRESS" },+ { 2826, "UDN_PENDING" },+ { 2827, "UDN_ROUTE_ORDER" },+ { 2828, "UDN_SP_FIFO_CNT" },+ { 2944, "UDN_DATA_AVAIL" },+ { 3072, "MPL_SWINT_3_SET_0" },+ { 3073, "MPL_SWINT_3_SET_1" },+ { 3074, "MPL_SWINT_3_SET_2" },+ { 3075, "MPL_SWINT_3_SET_3" },+ { 3076, "MPL_SWINT_3" },+ { 3328, "MPL_SWINT_2_SET_0" },+ { 3329, "MPL_SWINT_2_SET_1" },+ { 3330, "MPL_SWINT_2_SET_2" },+ { 3331, "MPL_SWINT_2_SET_3" },+ { 3332, "MPL_SWINT_2" },+ { 3584, "MPL_SWINT_1_SET_0" },+ { 3585, "MPL_SWINT_1_SET_1" },+ { 3586, "MPL_SWINT_1_SET_2" },+ { 3587, "MPL_SWINT_1_SET_3" },+ { 3588, "MPL_SWINT_1" },+ { 3840, "MPL_SWINT_0_SET_0" },+ { 3841, "MPL_SWINT_0_SET_1" },+ { 3842, "MPL_SWINT_0_SET_2" },+ { 3843, "MPL_SWINT_0_SET_3" },+ { 3844, "MPL_SWINT_0" },+ { 4096, "MPL_ILL_TRANS_SET_0" },+ { 4097, "MPL_ILL_TRANS_SET_1" },+ { 4098, "MPL_ILL_TRANS_SET_2" },+ { 4099, "MPL_ILL_TRANS_SET_3" },+ { 4100, "MPL_ILL_TRANS" },+ { 4101, "ILL_TRANS_REASON" },+ { 4102, "ILL_VA_PC" },+ { 4352, "MPL_UNALIGN_DATA_SET_0" },+ { 4353, "MPL_UNALIGN_DATA_SET_1" },+ { 4354, "MPL_UNALIGN_DATA_SET_2" },+ { 4355, "MPL_UNALIGN_DATA_SET_3" },+ { 4356, "MPL_UNALIGN_DATA" },+ { 4608, "MPL_DTLB_MISS_SET_0" },+ { 4609, "MPL_DTLB_MISS_SET_1" },+ { 4610, "MPL_DTLB_MISS_SET_2" },+ { 4611, "MPL_DTLB_MISS_SET_3" },+ { 4612, "MPL_DTLB_MISS" },+ { 4613, "DTLB_TSB_BASE_ADDR_0" },+ { 4614, "DTLB_TSB_BASE_ADDR_1" },+ { 4736, "AAR" },+ { 4737, "CACHE_PINNED_WAYS" },+ { 4738, "DTLB_BAD_ADDR" },+ { 4739, "DTLB_BAD_ADDR_REASON" },+ { 4740, "DTLB_CURRENT_ATTR" },+ { 4741, "DTLB_CURRENT_PA" },+ { 4742, "DTLB_CURRENT_VA" },+ { 4743, "DTLB_INDEX" },+ { 4744, "DTLB_MATCH_0" },+ { 4745, "DTLB_PERF" },+ { 4746, "DTLB_TSB_ADDR_0" },+ { 4747, "DTLB_TSB_ADDR_1" },+ { 4748, "DTLB_TSB_FILL_CURRENT_ATTR" },+ { 4749, "DTLB_TSB_FILL_MATCH" },+ { 4750, "NUMBER_DTLB" },+ { 4751, "REPLACEMENT_DTLB" },+ { 4752, "WIRED_DTLB" },+ { 4864, "MPL_DTLB_ACCESS_SET_0" },+ { 4865, "MPL_DTLB_ACCESS_SET_1" },+ { 4866, "MPL_DTLB_ACCESS_SET_2" },+ { 4867, "MPL_DTLB_ACCESS_SET_3" },+ { 4868, "MPL_DTLB_ACCESS" },+ { 5120, "MPL_IDN_FIREWALL_SET_0" },+ { 5121, "MPL_IDN_FIREWALL_SET_1" },+ { 5122, "MPL_IDN_FIREWALL_SET_2" },+ { 5123, "MPL_IDN_FIREWALL_SET_3" },+ { 5124, "MPL_IDN_FIREWALL" },+ { 5125, "IDN_DIRECTION_PROTECT" },+ { 5376, "MPL_UDN_FIREWALL_SET_0" },+ { 5377, "MPL_UDN_FIREWALL_SET_1" },+ { 5378, "MPL_UDN_FIREWALL_SET_2" },+ { 5379, "MPL_UDN_FIREWALL_SET_3" },+ { 5380, "MPL_UDN_FIREWALL" },+ { 5381, "UDN_DIRECTION_PROTECT" },+ { 5632, "MPL_TILE_TIMER_SET_0" },+ { 5633, "MPL_TILE_TIMER_SET_1" },+ { 5634, "MPL_TILE_TIMER_SET_2" },+ { 5635, "MPL_TILE_TIMER_SET_3" },+ { 5636, "MPL_TILE_TIMER" },+ { 5637, "TILE_TIMER_CONTROL" },+ { 5888, "MPL_AUX_TILE_TIMER_SET_0" },+ { 5889, "MPL_AUX_TILE_TIMER_SET_1" },+ { 5890, "MPL_AUX_TILE_TIMER_SET_2" },+ { 5891, "MPL_AUX_TILE_TIMER_SET_3" },+ { 5892, "MPL_AUX_TILE_TIMER" },+ { 5893, "AUX_TILE_TIMER_CONTROL" },+ { 6144, "MPL_IDN_TIMER_SET_0" },+ { 6145, "MPL_IDN_TIMER_SET_1" },+ { 6146, "MPL_IDN_TIMER_SET_2" },+ { 6147, "MPL_IDN_TIMER_SET_3" },+ { 6148, "MPL_IDN_TIMER" },+ { 6149, "IDN_DEADLOCK_COUNT" },+ { 6150, "IDN_DEADLOCK_TIMEOUT" },+ { 6400, "MPL_UDN_TIMER_SET_0" },+ { 6401, "MPL_UDN_TIMER_SET_1" },+ { 6402, "MPL_UDN_TIMER_SET_2" },+ { 6403, "MPL_UDN_TIMER_SET_3" },+ { 6404, "MPL_UDN_TIMER" },+ { 6405, "UDN_DEADLOCK_COUNT" },+ { 6406, "UDN_DEADLOCK_TIMEOUT" },+ { 6656, "MPL_IDN_AVAIL_SET_0" },+ { 6657, "MPL_IDN_AVAIL_SET_1" },+ { 6658, "MPL_IDN_AVAIL_SET_2" },+ { 6659, "MPL_IDN_AVAIL_SET_3" },+ { 6660, "MPL_IDN_AVAIL" },+ { 6661, "IDN_AVAIL_EN" },+ { 6912, "MPL_UDN_AVAIL_SET_0" },+ { 6913, "MPL_UDN_AVAIL_SET_1" },+ { 6914, "MPL_UDN_AVAIL_SET_2" },+ { 6915, "MPL_UDN_AVAIL_SET_3" },+ { 6916, "MPL_UDN_AVAIL" },+ { 6917, "UDN_AVAIL_EN" },+ { 7168, "MPL_IPI_3_SET_0" },+ { 7169, "MPL_IPI_3_SET_1" },+ { 7170, "MPL_IPI_3_SET_2" },+ { 7171, "MPL_IPI_3_SET_3" },+ { 7172, "MPL_IPI_3" },+ { 7173, "IPI_EVENT_3" },+ { 7174, "IPI_EVENT_RESET_3" },+ { 7175, "IPI_EVENT_SET_3" },+ { 7176, "IPI_MASK_3" },+ { 7177, "IPI_MASK_RESET_3" },+ { 7178, "IPI_MASK_SET_3" },+ { 7424, "MPL_IPI_2_SET_0" },+ { 7425, "MPL_IPI_2_SET_1" },+ { 7426, "MPL_IPI_2_SET_2" },+ { 7427, "MPL_IPI_2_SET_3" },+ { 7428, "MPL_IPI_2" },+ { 7429, "IPI_EVENT_2" },+ { 7430, "IPI_EVENT_RESET_2" },+ { 7431, "IPI_EVENT_SET_2" },+ { 7432, "IPI_MASK_2" },+ { 7433, "IPI_MASK_RESET_2" },+ { 7434, "IPI_MASK_SET_2" },+ { 7680, "MPL_IPI_1_SET_0" },+ { 7681, "MPL_IPI_1_SET_1" },+ { 7682, "MPL_IPI_1_SET_2" },+ { 7683, "MPL_IPI_1_SET_3" },+ { 7684, "MPL_IPI_1" },+ { 7685, "IPI_EVENT_1" },+ { 7686, "IPI_EVENT_RESET_1" },+ { 7687, "IPI_EVENT_SET_1" },+ { 7688, "IPI_MASK_1" },+ { 7689, "IPI_MASK_RESET_1" },+ { 7690, "IPI_MASK_SET_1" },+ { 7936, "MPL_IPI_0_SET_0" },+ { 7937, "MPL_IPI_0_SET_1" },+ { 7938, "MPL_IPI_0_SET_2" },+ { 7939, "MPL_IPI_0_SET_3" },+ { 7940, "MPL_IPI_0" },+ { 7941, "IPI_EVENT_0" },+ { 7942, "IPI_EVENT_RESET_0" },+ { 7943, "IPI_EVENT_SET_0" },+ { 7944, "IPI_MASK_0" },+ { 7945, "IPI_MASK_RESET_0" },+ { 7946, "IPI_MASK_SET_0" },+ { 8192, "MPL_PERF_COUNT_SET_0" },+ { 8193, "MPL_PERF_COUNT_SET_1" },+ { 8194, "MPL_PERF_COUNT_SET_2" },+ { 8195, "MPL_PERF_COUNT_SET_3" },+ { 8196, "MPL_PERF_COUNT" },+ { 8197, "PERF_COUNT_0" },+ { 8198, "PERF_COUNT_1" },+ { 8199, "PERF_COUNT_CTL" },+ { 8200, "PERF_COUNT_DN_CTL" },+ { 8201, "PERF_COUNT_STS" },+ { 8202, "WATCH_MASK" },+ { 8203, "WATCH_VAL" },+ { 8448, "MPL_AUX_PERF_COUNT_SET_0" },+ { 8449, "MPL_AUX_PERF_COUNT_SET_1" },+ { 8450, "MPL_AUX_PERF_COUNT_SET_2" },+ { 8451, "MPL_AUX_PERF_COUNT_SET_3" },+ { 8452, "MPL_AUX_PERF_COUNT" },+ { 8453, "AUX_PERF_COUNT_0" },+ { 8454, "AUX_PERF_COUNT_1" },+ { 8455, "AUX_PERF_COUNT_CTL" },+ { 8456, "AUX_PERF_COUNT_STS" },+ { 8704, "MPL_INTCTRL_3_SET_0" },+ { 8705, "MPL_INTCTRL_3_SET_1" },+ { 8706, "MPL_INTCTRL_3_SET_2" },+ { 8707, "MPL_INTCTRL_3_SET_3" },+ { 8708, "MPL_INTCTRL_3" },+ { 8709, "INTCTRL_3_STATUS" },+ { 8710, "INTERRUPT_MASK_3" },+ { 8711, "INTERRUPT_MASK_RESET_3" },+ { 8712, "INTERRUPT_MASK_SET_3" },+ { 8713, "INTERRUPT_VECTOR_BASE_3" },+ { 8714, "SINGLE_STEP_EN_0_3" },+ { 8715, "SINGLE_STEP_EN_1_3" },+ { 8716, "SINGLE_STEP_EN_2_3" },+ { 8717, "SINGLE_STEP_EN_3_3" },+ { 8832, "EX_CONTEXT_3_0" },+ { 8833, "EX_CONTEXT_3_1" },+ { 8834, "SYSTEM_SAVE_3_0" },+ { 8835, "SYSTEM_SAVE_3_1" },+ { 8836, "SYSTEM_SAVE_3_2" },+ { 8837, "SYSTEM_SAVE_3_3" },+ { 8960, "MPL_INTCTRL_2_SET_0" },+ { 8961, "MPL_INTCTRL_2_SET_1" },+ { 8962, "MPL_INTCTRL_2_SET_2" },+ { 8963, "MPL_INTCTRL_2_SET_3" },+ { 8964, "MPL_INTCTRL_2" },+ { 8965, "INTCTRL_2_STATUS" },+ { 8966, "INTERRUPT_MASK_2" },+ { 8967, "INTERRUPT_MASK_RESET_2" },+ { 8968, "INTERRUPT_MASK_SET_2" },+ { 8969, "INTERRUPT_VECTOR_BASE_2" },+ { 8970, "SINGLE_STEP_EN_0_2" },+ { 8971, "SINGLE_STEP_EN_1_2" },+ { 8972, "SINGLE_STEP_EN_2_2" },+ { 8973, "SINGLE_STEP_EN_3_2" },+ { 9088, "EX_CONTEXT_2_0" },+ { 9089, "EX_CONTEXT_2_1" },+ { 9090, "SYSTEM_SAVE_2_0" },+ { 9091, "SYSTEM_SAVE_2_1" },+ { 9092, "SYSTEM_SAVE_2_2" },+ { 9093, "SYSTEM_SAVE_2_3" },+ { 9216, "MPL_INTCTRL_1_SET_0" },+ { 9217, "MPL_INTCTRL_1_SET_1" },+ { 9218, "MPL_INTCTRL_1_SET_2" },+ { 9219, "MPL_INTCTRL_1_SET_3" },+ { 9220, "MPL_INTCTRL_1" },+ { 9221, "INTCTRL_1_STATUS" },+ { 9222, "INTERRUPT_MASK_1" },+ { 9223, "INTERRUPT_MASK_RESET_1" },+ { 9224, "INTERRUPT_MASK_SET_1" },+ { 9225, "INTERRUPT_VECTOR_BASE_1" },+ { 9226, "SINGLE_STEP_EN_0_1" },+ { 9227, "SINGLE_STEP_EN_1_1" },+ { 9228, "SINGLE_STEP_EN_2_1" },+ { 9229, "SINGLE_STEP_EN_3_1" },+ { 9344, "EX_CONTEXT_1_0" },+ { 9345, "EX_CONTEXT_1_1" },+ { 9346, "SYSTEM_SAVE_1_0" },+ { 9347, "SYSTEM_SAVE_1_1" },+ { 9348, "SYSTEM_SAVE_1_2" },+ { 9349, "SYSTEM_SAVE_1_3" },+ { 9472, "MPL_INTCTRL_0_SET_0" },+ { 9473, "MPL_INTCTRL_0_SET_1" },+ { 9474, "MPL_INTCTRL_0_SET_2" },+ { 9475, "MPL_INTCTRL_0_SET_3" },+ { 9476, "MPL_INTCTRL_0" },+ { 9477, "INTCTRL_0_STATUS" },+ { 9478, "INTERRUPT_MASK_0" },+ { 9479, "INTERRUPT_MASK_RESET_0" },+ { 9480, "INTERRUPT_MASK_SET_0" },+ { 9481, "INTERRUPT_VECTOR_BASE_0" },+ { 9482, "SINGLE_STEP_EN_0_0" },+ { 9483, "SINGLE_STEP_EN_1_0" },+ { 9484, "SINGLE_STEP_EN_2_0" },+ { 9485, "SINGLE_STEP_EN_3_0" },+ { 9600, "EX_CONTEXT_0_0" },+ { 9601, "EX_CONTEXT_0_1" },+ { 9602, "SYSTEM_SAVE_0_0" },+ { 9603, "SYSTEM_SAVE_0_1" },+ { 9604, "SYSTEM_SAVE_0_2" },+ { 9605, "SYSTEM_SAVE_0_3" },+ { 9728, "MPL_BOOT_ACCESS_SET_0" },+ { 9729, "MPL_BOOT_ACCESS_SET_1" },+ { 9730, "MPL_BOOT_ACCESS_SET_2" },+ { 9731, "MPL_BOOT_ACCESS_SET_3" },+ { 9732, "MPL_BOOT_ACCESS" },+ { 9733, "BIG_ENDIAN_CONFIG" },+ { 9734, "CACHE_INVALIDATION_COMPRESSION_MODE" },+ { 9735, "CACHE_INVALIDATION_MASK_0" },+ { 9736, "CACHE_INVALIDATION_MASK_1" },+ { 9737, "CACHE_INVALIDATION_MASK_2" },+ { 9738, "CBOX_CACHEASRAM_CONFIG" },+ { 9739, "CBOX_CACHE_CONFIG" },+ { 9740, "CBOX_HOME_MAP_ADDR" },+ { 9741, "CBOX_HOME_MAP_DATA" },+ { 9742, "CBOX_MMAP_0" },+ { 9743, "CBOX_MMAP_1" },+ { 9744, "CBOX_MMAP_2" },+ { 9745, "CBOX_MMAP_3" },+ { 9746, "CBOX_MSR" },+ { 9747, "DIAG_BCST_CTL" },+ { 9748, "DIAG_BCST_MASK" },+ { 9749, "DIAG_BCST_TRIGGER" },+ { 9750, "DIAG_MUX_CTL" },+ { 9751, "DIAG_TRACE_CTL" },+ { 9752, "DIAG_TRACE_DATA" },+ { 9753, "DIAG_TRACE_STS" },+ { 9754, "IDN_DEMUX_BUF_THRESH" },+ { 9755, "L1_I_PIN_WAY_0" },+ { 9756, "MEM_ROUTE_ORDER" },+ { 9757, "MEM_STRIPE_CONFIG" },+ { 9758, "PERF_COUNT_PLS" },+ { 9759, "PSEUDO_RANDOM_NUMBER_MODIFY" },+ { 9760, "QUIESCE_CTL" },+ { 9761, "RSHIM_COORD" },+ { 9762, "SBOX_CONFIG" },+ { 9763, "UDN_DEMUX_BUF_THRESH" },+ { 9764, "XDN_CORE_STARVATION_COUNT" },+ { 9765, "XDN_ROUND_ROBIN_ARB_CTL" },+ { 9856, "CYCLE_MODIFY" },+ { 9857, "I_AAR" },+ { 9984, "MPL_WORLD_ACCESS_SET_0" },+ { 9985, "MPL_WORLD_ACCESS_SET_1" },+ { 9986, "MPL_WORLD_ACCESS_SET_2" },+ { 9987, "MPL_WORLD_ACCESS_SET_3" },+ { 9988, "MPL_WORLD_ACCESS" },+ { 9989, "DONE" },+ { 9990, "DSTREAM_PF" },+ { 9991, "FAIL" },+ { 9992, "INTERRUPT_CRITICAL_SECTION" },+ { 9993, "PASS" },+ { 9994, "PSEUDO_RANDOM_NUMBER" },+ { 9995, "TILE_COORD" },+ { 9996, "TILE_RTF_HWM" },+ { 10112, "CMPEXCH_VALUE" },+ { 10113, "CYCLE" },+ { 10114, "EVENT_BEGIN" },+ { 10115, "EVENT_END" },+ { 10116, "PROC_STATUS" },+ { 10117, "SIM_CONTROL" },+ { 10118, "SIM_SOCKET" },+ { 10119, "STATUS_SATURATE" },+ { 10240, "MPL_I_ASID_SET_0" },+ { 10241, "MPL_I_ASID_SET_1" },+ { 10242, "MPL_I_ASID_SET_2" },+ { 10243, "MPL_I_ASID_SET_3" },+ { 10244, "MPL_I_ASID" },+ { 10245, "I_ASID" },+ { 10496, "MPL_D_ASID_SET_0" },+ { 10497, "MPL_D_ASID_SET_1" },+ { 10498, "MPL_D_ASID_SET_2" },+ { 10499, "MPL_D_ASID_SET_3" },+ { 10500, "MPL_D_ASID" },+ { 10501, "D_ASID" },+ { 10752, "MPL_DOUBLE_FAULT_SET_0" },+ { 10753, "MPL_DOUBLE_FAULT_SET_1" },+ { 10754, "MPL_DOUBLE_FAULT_SET_2" },+ { 10755, "MPL_DOUBLE_FAULT_SET_3" },+ { 10756, "MPL_DOUBLE_FAULT" },+ { 10757, "LAST_INTERRUPT_REASON" },+};++const int tilegx_num_sprs = 441;++const char *+get_tilegx_spr_name (int num)+{+ void *result;+ struct tilegx_spr key;++ key.number = num;+ result = bsearch((const void *) &key, (const void *) tilegx_sprs,+ tilegx_num_sprs, sizeof (struct tilegx_spr),+ tilegx_spr_compare);++ if (result == NULL)+ {+ return (NULL);+ }+ else+ {+ struct tilegx_spr *result_ptr = (struct tilegx_spr *) result;+ return (result_ptr->name);+ }+}++int+print_insn_tilegx (unsigned char * memaddr)+{+ struct tilegx_decoded_instruction+ decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];+ unsigned char opbuf[TILEGX_BUNDLE_SIZE_IN_BYTES];+ int i, num_instructions, num_printed;+ tilegx_mnemonic padding_mnemonic;++ memcpy((void *)opbuf, (void *)memaddr, TILEGX_BUNDLE_SIZE_IN_BYTES);++ /* Parse the instructions in the bundle. */+ num_instructions =+ parse_insn_tilegx (*(unsigned long long *)opbuf, (unsigned long long)memaddr, decoded);++ /* Print the instructions in the bundle. */+ printf("{ ");+ num_printed = 0;++ /* Determine which nop opcode is used for padding and should be skipped. */+ padding_mnemonic = TILEGX_OPC_FNOP;+ for (i = 0; i < num_instructions; i++)+ {+ if (!decoded[i].opcode->can_bundle)+ {+ /* Instructions that cannot be bundled are padded out with nops,+ rather than fnops. Displaying them is always clutter. */+ padding_mnemonic = TILEGX_OPC_NOP;+ break;+ }+ }++ for (i = 0; i < num_instructions; i++)+ {+ const struct tilegx_opcode *opcode = decoded[i].opcode;+ const char *name;+ int j;++ /* Do not print out fnops, unless everything is an fnop, in+ which case we will print out just the last one. */+ if (opcode->mnemonic == padding_mnemonic+ && (num_printed > 0 || i + 1 < num_instructions))+ continue;++ if (num_printed > 0)+ printf(" ; ");+ ++num_printed;++ name = opcode->name;+ if (name == NULL)+ name = "<invalid>";+ printf("%s", name);++ for (j = 0; j < opcode->num_operands; j++)+ {+ unsigned long long num;+ const struct tilegx_operand *op;+ const char *spr_name;++ if (j > 0)+ printf (",");+ printf (" ");++ num = decoded[i].operand_values[j];++ op = decoded[i].operands[j];+ switch (op->type)+ {+ case TILEGX_OP_TYPE_REGISTER:+ printf ("%s", tilegx_register_names[(int)num]);+ break;+ case TILEGX_OP_TYPE_SPR:+ spr_name = get_tilegx_spr_name(num);+ if (spr_name != NULL)+ printf ("%s", spr_name);+ else+ printf ("%d", (int)num);+ break;+ case TILEGX_OP_TYPE_IMMEDIATE:+ printf ("%d", (int)num);+ break;+ case TILEGX_OP_TYPE_ADDRESS:+ printf ("0x%016llx", num);+ break;+ default:+ abort ();+ }+ }+ }+ printf (" }\n");++ return TILEGX_BUNDLE_SIZE_IN_BYTES;+}
+ src/c/pcre2/src/sljit/sljitNativeTILEGX_64.c view
@@ -0,0 +1,2565 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved.+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/* TileGX architecture. */+/* Contributed by Tilera Corporation. */+#include "sljitNativeTILEGX-encoder.c"++#define SIMM_8BIT_MAX (0x7f)+#define SIMM_8BIT_MIN (-0x80)+#define SIMM_16BIT_MAX (0x7fff)+#define SIMM_16BIT_MIN (-0x8000)+#define SIMM_17BIT_MAX (0xffff)+#define SIMM_17BIT_MIN (-0x10000)+#define SIMM_32BIT_MAX (0x7fffffff)+#define SIMM_32BIT_MIN (-0x7fffffff - 1)+#define SIMM_48BIT_MAX (0x7fffffff0000L)+#define SIMM_48BIT_MIN (-0x800000000000L)+#define IMM16(imm) ((imm) & 0xffff)++#define UIMM_16BIT_MAX (0xffff)++#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)+#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)+#define ADDR_TMP (SLJIT_NUMBER_OF_REGISTERS + 5)+#define PIC_ADDR_REG TMP_REG2++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {+ 63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7+};++#define SLJIT_LOCALS_REG_mapped 54+#define TMP_REG1_mapped 5+#define TMP_REG2_mapped 16+#define TMP_REG3_mapped 6+#define ADDR_TMP_mapped 7++/* Flags are keept in volatile registers. */+#define EQUAL_FLAG 8+/* And carry flag as well. */+#define ULESS_FLAG 9+#define UGREATER_FLAG 10+#define LESS_FLAG 11+#define GREATER_FLAG 12+#define OVERFLOW_FLAG 13++#define ZERO 63+#define RA 55+#define TMP_EREG1 14+#define TMP_EREG2 15++#define LOAD_DATA 0x01+#define WORD_DATA 0x00+#define BYTE_DATA 0x02+#define HALF_DATA 0x04+#define INT_DATA 0x06+#define SIGNED_DATA 0x08+#define DOUBLE_DATA 0x10++/* Separates integer and floating point registers */+#define GPR_REG 0xf++#define MEM_MASK 0x1f++#define WRITE_BACK 0x00020+#define ARG_TEST 0x00040+#define ALT_KEEP_CACHE 0x00080+#define CUMULATIVE_OP 0x00100+#define LOGICAL_OP 0x00200+#define IMM_OP 0x00400+#define SRC2_IMM 0x00800++#define UNUSED_DEST 0x01000+#define REG_DEST 0x02000+#define REG1_SOURCE 0x04000+#define REG2_SOURCE 0x08000+#define SLOW_SRC1 0x10000+#define SLOW_SRC2 0x20000+#define SLOW_DEST 0x40000++/* Only these flags are set. UNUSED_DEST is not set when no flags should be set.+ */+#define CHECK_FLAGS(list) (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list))))++SLJIT_API_FUNC_ATTRIBUTE const char *sljit_get_platform_name(void)+{+ return "TileGX" SLJIT_CPUINFO;+}++/* Length of an instruction word */+typedef sljit_uw sljit_ins;++struct jit_instr {+ const struct tilegx_opcode* opcode; + tilegx_pipeline pipe;+ unsigned long input_registers;+ unsigned long output_registers;+ int operand_value[4];+ int line;+};++/* Opcode Helper Macros */+#define TILEGX_X_MODE 0++#define X_MODE create_Mode(TILEGX_X_MODE)++#define FNOP_X0 \+ create_Opcode_X0(RRR_0_OPCODE_X0) | \+ create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \+ create_UnaryOpcodeExtension_X0(FNOP_UNARY_OPCODE_X0)++#define FNOP_X1 \+ create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \+ create_UnaryOpcodeExtension_X1(FNOP_UNARY_OPCODE_X1)++#define NOP \+ create_Mode(TILEGX_X_MODE) | FNOP_X0 | FNOP_X1++#define ANOP_X0 \+ create_Opcode_X0(RRR_0_OPCODE_X0) | \+ create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \+ create_UnaryOpcodeExtension_X0(NOP_UNARY_OPCODE_X0)++#define BPT create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \+ create_UnaryOpcodeExtension_X1(ILL_UNARY_OPCODE_X1) | \+ create_Dest_X1(0x1C) | create_SrcA_X1(0x25) | ANOP_X0++#define ADD_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(ADD_RRR_0_OPCODE_X1) | FNOP_X0++#define ADDI_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \+ create_Imm8OpcodeExtension_X1(ADDI_IMM8_OPCODE_X1) | FNOP_X0++#define SUB_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(SUB_RRR_0_OPCODE_X1) | FNOP_X0++#define NOR_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(NOR_RRR_0_OPCODE_X1) | FNOP_X0++#define OR_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(OR_RRR_0_OPCODE_X1) | FNOP_X0++#define AND_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(AND_RRR_0_OPCODE_X1) | FNOP_X0++#define XOR_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(XOR_RRR_0_OPCODE_X1) | FNOP_X0++#define CMOVNEZ_X0 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \+ create_RRROpcodeExtension_X0(CMOVNEZ_RRR_0_OPCODE_X0) | FNOP_X1++#define CMOVEQZ_X0 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \+ create_RRROpcodeExtension_X0(CMOVEQZ_RRR_0_OPCODE_X0) | FNOP_X1++#define ADDLI_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(ADDLI_OPCODE_X1) | FNOP_X0++#define V4INT_L_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(V4INT_L_RRR_0_OPCODE_X1) | FNOP_X0++#define BFEXTU_X0 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(BF_OPCODE_X0) | \+ create_BFOpcodeExtension_X0(BFEXTU_BF_OPCODE_X0) | FNOP_X1++#define BFEXTS_X0 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(BF_OPCODE_X0) | \+ create_BFOpcodeExtension_X0(BFEXTS_BF_OPCODE_X0) | FNOP_X1++#define SHL16INSLI_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHL16INSLI_OPCODE_X1) | FNOP_X0++#define ST_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(ST_RRR_0_OPCODE_X1) | create_Dest_X1(0x0) | FNOP_X0++#define LD_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \+ create_UnaryOpcodeExtension_X1(LD_UNARY_OPCODE_X1) | FNOP_X0++#define JR_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \+ create_UnaryOpcodeExtension_X1(JR_UNARY_OPCODE_X1) | FNOP_X0++#define JALR_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \+ create_UnaryOpcodeExtension_X1(JALR_UNARY_OPCODE_X1) | FNOP_X0++#define CLZ_X0 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \+ create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \+ create_UnaryOpcodeExtension_X0(CNTLZ_UNARY_OPCODE_X0) | FNOP_X1++#define CMPLTUI_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \+ create_Imm8OpcodeExtension_X1(CMPLTUI_IMM8_OPCODE_X1) | FNOP_X0++#define CMPLTU_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(CMPLTU_RRR_0_OPCODE_X1) | FNOP_X0++#define CMPLTS_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(CMPLTS_RRR_0_OPCODE_X1) | FNOP_X0++#define XORI_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \+ create_Imm8OpcodeExtension_X1(XORI_IMM8_OPCODE_X1) | FNOP_X0++#define ORI_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \+ create_Imm8OpcodeExtension_X1(ORI_IMM8_OPCODE_X1) | FNOP_X0++#define ANDI_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \+ create_Imm8OpcodeExtension_X1(ANDI_IMM8_OPCODE_X1) | FNOP_X0++#define SHLI_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \+ create_ShiftOpcodeExtension_X1(SHLI_SHIFT_OPCODE_X1) | FNOP_X0++#define SHL_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(SHL_RRR_0_OPCODE_X1) | FNOP_X0++#define SHRSI_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \+ create_ShiftOpcodeExtension_X1(SHRSI_SHIFT_OPCODE_X1) | FNOP_X0++#define SHRS_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(SHRS_RRR_0_OPCODE_X1) | FNOP_X0++#define SHRUI_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \+ create_ShiftOpcodeExtension_X1(SHRUI_SHIFT_OPCODE_X1) | FNOP_X0++#define SHRU_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \+ create_RRROpcodeExtension_X1(SHRU_RRR_0_OPCODE_X1) | FNOP_X0++#define BEQZ_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(BRANCH_OPCODE_X1) | \+ create_BrType_X1(BEQZ_BRANCH_OPCODE_X1) | FNOP_X0++#define BNEZ_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(BRANCH_OPCODE_X1) | \+ create_BrType_X1(BNEZ_BRANCH_OPCODE_X1) | FNOP_X0++#define J_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(JUMP_OPCODE_X1) | \+ create_JumpOpcodeExtension_X1(J_JUMP_OPCODE_X1) | FNOP_X0++#define JAL_X1 \+ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(JUMP_OPCODE_X1) | \+ create_JumpOpcodeExtension_X1(JAL_JUMP_OPCODE_X1) | FNOP_X0++#define DEST_X0(x) create_Dest_X0(x)+#define SRCA_X0(x) create_SrcA_X0(x)+#define SRCB_X0(x) create_SrcB_X0(x)+#define DEST_X1(x) create_Dest_X1(x)+#define SRCA_X1(x) create_SrcA_X1(x)+#define SRCB_X1(x) create_SrcB_X1(x)+#define IMM16_X1(x) create_Imm16_X1(x)+#define IMM8_X1(x) create_Imm8_X1(x)+#define BFSTART_X0(x) create_BFStart_X0(x)+#define BFEND_X0(x) create_BFEnd_X0(x)+#define SHIFTIMM_X1(x) create_ShAmt_X1(x)+#define JOFF_X1(x) create_JumpOff_X1(x)+#define BOFF_X1(x) create_BrOff_X1(x)++static const tilegx_mnemonic data_transfer_insts[16] = {+ /* u w s */ TILEGX_OPC_ST /* st */,+ /* u w l */ TILEGX_OPC_LD /* ld */,+ /* u b s */ TILEGX_OPC_ST1 /* st1 */,+ /* u b l */ TILEGX_OPC_LD1U /* ld1u */,+ /* u h s */ TILEGX_OPC_ST2 /* st2 */,+ /* u h l */ TILEGX_OPC_LD2U /* ld2u */,+ /* u i s */ TILEGX_OPC_ST4 /* st4 */,+ /* u i l */ TILEGX_OPC_LD4U /* ld4u */,+ /* s w s */ TILEGX_OPC_ST /* st */,+ /* s w l */ TILEGX_OPC_LD /* ld */,+ /* s b s */ TILEGX_OPC_ST1 /* st1 */,+ /* s b l */ TILEGX_OPC_LD1S /* ld1s */,+ /* s h s */ TILEGX_OPC_ST2 /* st2 */,+ /* s h l */ TILEGX_OPC_LD2S /* ld2s */,+ /* s i s */ TILEGX_OPC_ST4 /* st4 */,+ /* s i l */ TILEGX_OPC_LD4S /* ld4s */,+};++#ifdef TILEGX_JIT_DEBUG+static sljit_s32 push_inst_debug(struct sljit_compiler *compiler, sljit_ins ins, int line)+{+ sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ *ptr = ins;+ compiler->size++;+ printf("|%04d|S0|:\t\t", line);+ print_insn_tilegx(ptr);+ return SLJIT_SUCCESS;+}++static sljit_s32 push_inst_nodebug(struct sljit_compiler *compiler, sljit_ins ins)+{+ sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ *ptr = ins;+ compiler->size++;+ return SLJIT_SUCCESS;+}++#define push_inst(a, b) push_inst_debug(a, b, __LINE__)+#else+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)+{+ sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ *ptr = ins;+ compiler->size++;+ return SLJIT_SUCCESS;+}+#endif++#define BUNDLE_FORMAT_MASK(p0, p1, p2) \+ ((p0) | ((p1) << 8) | ((p2) << 16))++#define BUNDLE_FORMAT(p0, p1, p2) \+ { \+ { \+ (tilegx_pipeline)(p0), \+ (tilegx_pipeline)(p1), \+ (tilegx_pipeline)(p2) \+ }, \+ BUNDLE_FORMAT_MASK(1 << (p0), 1 << (p1), (1 << (p2))) \+ }++#define NO_PIPELINE TILEGX_NUM_PIPELINE_ENCODINGS++#define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1)++#define PI(encoding) \+ push_inst(compiler, encoding)++#define PB3(opcode, dst, srca, srcb) \+ push_3_buffer(compiler, opcode, dst, srca, srcb, __LINE__)++#define PB2(opcode, dst, src) \+ push_2_buffer(compiler, opcode, dst, src, __LINE__)++#define JR(reg) \+ push_jr_buffer(compiler, TILEGX_OPC_JR, reg, __LINE__)++#define ADD(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_ADD, dst, srca, srcb, __LINE__)++#define SUB(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_SUB, dst, srca, srcb, __LINE__)++#define MUL(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_MULX, dst, srca, srcb, __LINE__)++#define NOR(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_NOR, dst, srca, srcb, __LINE__)++#define OR(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_OR, dst, srca, srcb, __LINE__)++#define XOR(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_XOR, dst, srca, srcb, __LINE__)++#define AND(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_AND, dst, srca, srcb, __LINE__)++#define CLZ(dst, src) \+ push_2_buffer(compiler, TILEGX_OPC_CLZ, dst, src, __LINE__)++#define SHLI(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_SHLI, dst, srca, srcb, __LINE__)++#define SHRUI(dst, srca, imm) \+ push_3_buffer(compiler, TILEGX_OPC_SHRUI, dst, srca, imm, __LINE__)++#define XORI(dst, srca, imm) \+ push_3_buffer(compiler, TILEGX_OPC_XORI, dst, srca, imm, __LINE__)++#define ORI(dst, srca, imm) \+ push_3_buffer(compiler, TILEGX_OPC_ORI, dst, srca, imm, __LINE__)++#define CMPLTU(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_CMPLTU, dst, srca, srcb, __LINE__)++#define CMPLTS(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_CMPLTS, dst, srca, srcb, __LINE__)++#define CMPLTUI(dst, srca, imm) \+ push_3_buffer(compiler, TILEGX_OPC_CMPLTUI, dst, srca, imm, __LINE__)++#define CMOVNEZ(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_CMOVNEZ, dst, srca, srcb, __LINE__)++#define CMOVEQZ(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_CMOVEQZ, dst, srca, srcb, __LINE__)++#define ADDLI(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_ADDLI, dst, srca, srcb, __LINE__)++#define SHL16INSLI(dst, srca, srcb) \+ push_3_buffer(compiler, TILEGX_OPC_SHL16INSLI, dst, srca, srcb, __LINE__)++#define LD_ADD(dst, addr, adjust) \+ push_3_buffer(compiler, TILEGX_OPC_LD_ADD, dst, addr, adjust, __LINE__)++#define ST_ADD(src, addr, adjust) \+ push_3_buffer(compiler, TILEGX_OPC_ST_ADD, src, addr, adjust, __LINE__)++#define LD(dst, addr) \+ push_2_buffer(compiler, TILEGX_OPC_LD, dst, addr, __LINE__)++#define BFEXTU(dst, src, start, end) \+ push_4_buffer(compiler, TILEGX_OPC_BFEXTU, dst, src, start, end, __LINE__)++#define BFEXTS(dst, src, start, end) \+ push_4_buffer(compiler, TILEGX_OPC_BFEXTS, dst, src, start, end, __LINE__)++#define ADD_SOLO(dest, srca, srcb) \+ push_inst(compiler, ADD_X1 | DEST_X1(dest) | SRCA_X1(srca) | SRCB_X1(srcb))++#define ADDI_SOLO(dest, srca, imm) \+ push_inst(compiler, ADDI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM8_X1(imm))++#define ADDLI_SOLO(dest, srca, imm) \+ push_inst(compiler, ADDLI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM16_X1(imm))++#define SHL16INSLI_SOLO(dest, srca, imm) \+ push_inst(compiler, SHL16INSLI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM16_X1(imm))++#define JALR_SOLO(reg) \+ push_inst(compiler, JALR_X1 | SRCA_X1(reg))++#define JR_SOLO(reg) \+ push_inst(compiler, JR_X1 | SRCA_X1(reg))++struct Format {+ /* Mapping of bundle issue slot to assigned pipe. */+ tilegx_pipeline pipe[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];++ /* Mask of pipes used by this bundle. */+ unsigned int pipe_mask;+};++const struct Format formats[] =+{+ /* In Y format we must always have something in Y2, since it has+ * no fnop, so this conveys that Y2 must always be used. */+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2, NO_PIPELINE),+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2, NO_PIPELINE),+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0, NO_PIPELINE),+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1, NO_PIPELINE),++ /* Y format has three instructions. */+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2),+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1),+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2),+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0),+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y1),+ BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y0),++ /* X format has only two instructions. */+ BUNDLE_FORMAT(TILEGX_PIPELINE_X0, TILEGX_PIPELINE_X1, NO_PIPELINE),+ BUNDLE_FORMAT(TILEGX_PIPELINE_X1, TILEGX_PIPELINE_X0, NO_PIPELINE)+};+++struct jit_instr inst_buf[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];+unsigned long inst_buf_index;++tilegx_pipeline get_any_valid_pipe(const struct tilegx_opcode* opcode)+{+ /* FIXME: tile: we could pregenerate this. */+ int pipe;+ for (pipe = 0; ((opcode->pipes & (1 << pipe)) == 0 && pipe < TILEGX_NUM_PIPELINE_ENCODINGS); pipe++)+ ;+ return (tilegx_pipeline)(pipe);+}++void insert_nop(tilegx_mnemonic opc, int line)+{+ const struct tilegx_opcode* opcode = NULL;++ memmove(&inst_buf[1], &inst_buf[0], inst_buf_index * sizeof inst_buf[0]);++ opcode = &tilegx_opcodes[opc];+ inst_buf[0].opcode = opcode;+ inst_buf[0].pipe = get_any_valid_pipe(opcode);+ inst_buf[0].input_registers = 0;+ inst_buf[0].output_registers = 0;+ inst_buf[0].line = line;+ ++inst_buf_index;+}++const struct Format* compute_format()+{+ unsigned int compatible_pipes = BUNDLE_FORMAT_MASK(+ inst_buf[0].opcode->pipes,+ inst_buf[1].opcode->pipes,+ (inst_buf_index == 3 ? inst_buf[2].opcode->pipes : (1 << NO_PIPELINE)));++ const struct Format* match = NULL;+ const struct Format *b = NULL;+ unsigned int i;+ for (i = 0; i < sizeof formats / sizeof formats[0]; i++) {+ b = &formats[i];+ if ((b->pipe_mask & compatible_pipes) == b->pipe_mask) {+ match = b;+ break;+ }+ }++ return match;+}++sljit_s32 assign_pipes()+{+ unsigned long output_registers = 0;+ unsigned int i = 0;++ if (inst_buf_index == 1) {+ tilegx_mnemonic opc = inst_buf[0].opcode->can_bundle+ ? TILEGX_OPC_FNOP : TILEGX_OPC_NOP;+ insert_nop(opc, __LINE__);+ }++ const struct Format* match = compute_format();++ if (match == NULL)+ return -1;++ for (i = 0; i < inst_buf_index; i++) {++ if ((i > 0) && ((inst_buf[i].input_registers & output_registers) != 0))+ return -1;++ if ((i > 0) && ((inst_buf[i].output_registers & output_registers) != 0))+ return -1;++ /* Don't include Rzero in the match set, to avoid triggering+ needlessly on 'prefetch' instrs. */++ output_registers |= inst_buf[i].output_registers & 0xFFFFFFFFFFFFFFL;++ inst_buf[i].pipe = match->pipe[i];+ }++ /* If only 2 instrs, and in Y-mode, insert a nop. */+ if (inst_buf_index == 2 && !tilegx_is_x_pipeline(match->pipe[0])) {+ insert_nop(TILEGX_OPC_FNOP, __LINE__);++ /* Select the yet unassigned pipe. */+ tilegx_pipeline pipe = (tilegx_pipeline)(((TILEGX_PIPELINE_Y0+ + TILEGX_PIPELINE_Y1 + TILEGX_PIPELINE_Y2)+ - (inst_buf[1].pipe + inst_buf[2].pipe)));++ inst_buf[0].pipe = pipe;+ }++ return 0;+}++tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst)+{+ int i, val;+ const struct tilegx_opcode* opcode = inst->opcode;+ tilegx_bundle_bits bits = opcode->fixed_bit_values[inst->pipe];++ const struct tilegx_operand* operand = NULL;+ for (i = 0; i < opcode->num_operands; i++) {+ operand = &tilegx_operands[opcode->operands[inst->pipe][i]];+ val = inst->operand_value[i];++ bits |= operand->insert(val);+ }++ return bits;+}++static sljit_s32 update_buffer(struct sljit_compiler *compiler)+{+ int i;+ int orig_index = inst_buf_index;+ struct jit_instr inst0 = inst_buf[0];+ struct jit_instr inst1 = inst_buf[1];+ struct jit_instr inst2 = inst_buf[2];+ tilegx_bundle_bits bits = 0;++ /* If the bundle is valid as is, perform the encoding and return 1. */+ if (assign_pipes() == 0) {+ for (i = 0; i < inst_buf_index; i++) {+ bits |= get_bundle_bit(inst_buf + i);+#ifdef TILEGX_JIT_DEBUG+ printf("|%04d", inst_buf[i].line);+#endif+ }+#ifdef TILEGX_JIT_DEBUG+ if (inst_buf_index == 3)+ printf("|M0|:\t");+ else+ printf("|M0|:\t\t");+ print_insn_tilegx(&bits);+#endif++ inst_buf_index = 0;++#ifdef TILEGX_JIT_DEBUG+ return push_inst_nodebug(compiler, bits);+#else+ return push_inst(compiler, bits);+#endif+ }++ /* If the bundle is invalid, split it in two. First encode the first two+ (or possibly 1) instructions, and then the last, separately. Note that+ assign_pipes may have re-ordered the instrs (by inserting no-ops in+ lower slots) so we need to reset them. */++ inst_buf_index = orig_index - 1;+ inst_buf[0] = inst0;+ inst_buf[1] = inst1;+ inst_buf[2] = inst2;+ if (assign_pipes() == 0) {+ for (i = 0; i < inst_buf_index; i++) {+ bits |= get_bundle_bit(inst_buf + i);+#ifdef TILEGX_JIT_DEBUG+ printf("|%04d", inst_buf[i].line);+#endif+ }++#ifdef TILEGX_JIT_DEBUG+ if (inst_buf_index == 3)+ printf("|M1|:\t");+ else+ printf("|M1|:\t\t");+ print_insn_tilegx(&bits);+#endif++ if ((orig_index - 1) == 2) {+ inst_buf[0] = inst2;+ inst_buf_index = 1;+ } else if ((orig_index - 1) == 1) {+ inst_buf[0] = inst1;+ inst_buf_index = 1;+ } else+ SLJIT_UNREACHABLE();++#ifdef TILEGX_JIT_DEBUG+ return push_inst_nodebug(compiler, bits);+#else+ return push_inst(compiler, bits);+#endif+ } else {+ /* We had 3 instrs of which the first 2 can't live in the same bundle.+ Split those two. Note that we don't try to then combine the second+ and third instr into a single bundle. First instruction: */+ inst_buf_index = 1;+ inst_buf[0] = inst0;+ inst_buf[1] = inst1;+ inst_buf[2] = inst2;+ if (assign_pipes() == 0) {+ for (i = 0; i < inst_buf_index; i++) {+ bits |= get_bundle_bit(inst_buf + i);+#ifdef TILEGX_JIT_DEBUG+ printf("|%04d", inst_buf[i].line);+#endif+ }++#ifdef TILEGX_JIT_DEBUG+ if (inst_buf_index == 3)+ printf("|M2|:\t");+ else+ printf("|M2|:\t\t");+ print_insn_tilegx(&bits);+#endif++ inst_buf[0] = inst1;+ inst_buf[1] = inst2;+ inst_buf_index = orig_index - 1;+#ifdef TILEGX_JIT_DEBUG+ return push_inst_nodebug(compiler, bits);+#else+ return push_inst(compiler, bits);+#endif+ } else+ SLJIT_UNREACHABLE();+ }++ SLJIT_UNREACHABLE();+}++static sljit_s32 flush_buffer(struct sljit_compiler *compiler)+{+ while (inst_buf_index != 0) {+ FAIL_IF(update_buffer(compiler));+ }+ return SLJIT_SUCCESS;+}++static sljit_s32 push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line)+{+ if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)+ FAIL_IF(update_buffer(compiler));++ const struct tilegx_opcode* opcode = &tilegx_opcodes[opc];+ inst_buf[inst_buf_index].opcode = opcode;+ inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode);+ inst_buf[inst_buf_index].operand_value[0] = op0;+ inst_buf[inst_buf_index].operand_value[1] = op1;+ inst_buf[inst_buf_index].operand_value[2] = op2;+ inst_buf[inst_buf_index].operand_value[3] = op3;+ inst_buf[inst_buf_index].input_registers = 1L << op1;+ inst_buf[inst_buf_index].output_registers = 1L << op0;+ inst_buf[inst_buf_index].line = line;+ inst_buf_index++;++ return SLJIT_SUCCESS;+}++static sljit_s32 push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int line)+{+ if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)+ FAIL_IF(update_buffer(compiler));++ const struct tilegx_opcode* opcode = &tilegx_opcodes[opc];+ inst_buf[inst_buf_index].opcode = opcode;+ inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode);+ inst_buf[inst_buf_index].operand_value[0] = op0;+ inst_buf[inst_buf_index].operand_value[1] = op1;+ inst_buf[inst_buf_index].operand_value[2] = op2;+ inst_buf[inst_buf_index].line = line;++ switch (opc) {+ case TILEGX_OPC_ST_ADD:+ inst_buf[inst_buf_index].input_registers = (1L << op0) | (1L << op1);+ inst_buf[inst_buf_index].output_registers = 1L << op0;+ break;+ case TILEGX_OPC_LD_ADD:+ inst_buf[inst_buf_index].input_registers = 1L << op1;+ inst_buf[inst_buf_index].output_registers = (1L << op0) | (1L << op1);+ break;+ case TILEGX_OPC_ADD:+ case TILEGX_OPC_AND:+ case TILEGX_OPC_SUB:+ case TILEGX_OPC_MULX:+ case TILEGX_OPC_OR:+ case TILEGX_OPC_XOR:+ case TILEGX_OPC_NOR:+ case TILEGX_OPC_SHL:+ case TILEGX_OPC_SHRU:+ case TILEGX_OPC_SHRS:+ case TILEGX_OPC_CMPLTU:+ case TILEGX_OPC_CMPLTS:+ case TILEGX_OPC_CMOVEQZ:+ case TILEGX_OPC_CMOVNEZ:+ inst_buf[inst_buf_index].input_registers = (1L << op1) | (1L << op2);+ inst_buf[inst_buf_index].output_registers = 1L << op0;+ break;+ case TILEGX_OPC_ADDLI:+ case TILEGX_OPC_XORI:+ case TILEGX_OPC_ORI:+ case TILEGX_OPC_SHLI:+ case TILEGX_OPC_SHRUI:+ case TILEGX_OPC_SHRSI:+ case TILEGX_OPC_SHL16INSLI:+ case TILEGX_OPC_CMPLTUI:+ case TILEGX_OPC_CMPLTSI:+ inst_buf[inst_buf_index].input_registers = 1L << op1;+ inst_buf[inst_buf_index].output_registers = 1L << op0;+ break;+ default:+ printf("unrecoginzed opc: %s\n", opcode->name);+ SLJIT_UNREACHABLE();+ }++ inst_buf_index++;++ return SLJIT_SUCCESS;+}++static sljit_s32 push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int line)+{+ if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)+ FAIL_IF(update_buffer(compiler));++ const struct tilegx_opcode* opcode = &tilegx_opcodes[opc];+ inst_buf[inst_buf_index].opcode = opcode;+ inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode);+ inst_buf[inst_buf_index].operand_value[0] = op0;+ inst_buf[inst_buf_index].operand_value[1] = op1;+ inst_buf[inst_buf_index].line = line;++ switch (opc) {+ case TILEGX_OPC_BEQZ:+ case TILEGX_OPC_BNEZ:+ inst_buf[inst_buf_index].input_registers = 1L << op0;+ break;+ case TILEGX_OPC_ST:+ case TILEGX_OPC_ST1:+ case TILEGX_OPC_ST2:+ case TILEGX_OPC_ST4:+ inst_buf[inst_buf_index].input_registers = (1L << op0) | (1L << op1);+ inst_buf[inst_buf_index].output_registers = 0;+ break;+ case TILEGX_OPC_CLZ:+ case TILEGX_OPC_LD:+ case TILEGX_OPC_LD1U:+ case TILEGX_OPC_LD1S:+ case TILEGX_OPC_LD2U:+ case TILEGX_OPC_LD2S:+ case TILEGX_OPC_LD4U:+ case TILEGX_OPC_LD4S:+ inst_buf[inst_buf_index].input_registers = 1L << op1;+ inst_buf[inst_buf_index].output_registers = 1L << op0;+ break;+ default:+ printf("unrecoginzed opc: %s\n", opcode->name);+ SLJIT_UNREACHABLE();+ }++ inst_buf_index++;++ return SLJIT_SUCCESS;+}++static sljit_s32 push_0_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int line)+{+ if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)+ FAIL_IF(update_buffer(compiler));++ const struct tilegx_opcode* opcode = &tilegx_opcodes[opc];+ inst_buf[inst_buf_index].opcode = opcode;+ inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode);+ inst_buf[inst_buf_index].input_registers = 0;+ inst_buf[inst_buf_index].output_registers = 0;+ inst_buf[inst_buf_index].line = line;+ inst_buf_index++;++ return SLJIT_SUCCESS;+}++static sljit_s32 push_jr_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int line)+{+ if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE)+ FAIL_IF(update_buffer(compiler));++ const struct tilegx_opcode* opcode = &tilegx_opcodes[opc];+ inst_buf[inst_buf_index].opcode = opcode;+ inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode);+ inst_buf[inst_buf_index].operand_value[0] = op0;+ inst_buf[inst_buf_index].input_registers = 1L << op0;+ inst_buf[inst_buf_index].output_registers = 0;+ inst_buf[inst_buf_index].line = line;+ inst_buf_index++;+ + return flush_buffer(compiler);+}++static SLJIT_INLINE sljit_ins * detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)+{+ sljit_sw diff;+ sljit_uw target_addr;+ sljit_ins *inst;++ if (jump->flags & SLJIT_REWRITABLE_JUMP)+ return code_ptr;++ if (jump->flags & JUMP_ADDR)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->flags & JUMP_LABEL);+ target_addr = (sljit_uw)(code + jump->u.label->size);+ }++ inst = (sljit_ins *)jump->addr;+ if (jump->flags & IS_COND)+ inst--;++ diff = ((sljit_sw) target_addr - (sljit_sw) inst) >> 3;+ if (diff <= SIMM_17BIT_MAX && diff >= SIMM_17BIT_MIN) {+ jump->flags |= PATCH_B;++ if (!(jump->flags & IS_COND)) {+ if (jump->flags & IS_JAL) {+ jump->flags &= ~(PATCH_B);+ jump->flags |= PATCH_J;+ inst[0] = JAL_X1;++#ifdef TILEGX_JIT_DEBUG+ printf("[runtime relocate]%04d:\t", __LINE__);+ print_insn_tilegx(inst);+#endif+ } else {+ inst[0] = BEQZ_X1 | SRCA_X1(ZERO);++#ifdef TILEGX_JIT_DEBUG+ printf("[runtime relocate]%04d:\t", __LINE__);+ print_insn_tilegx(inst);+#endif+ }++ return inst;+ }++ inst[0] = inst[0] ^ (0x7L << 55);++#ifdef TILEGX_JIT_DEBUG+ printf("[runtime relocate]%04d:\t", __LINE__);+ print_insn_tilegx(inst);+#endif+ jump->addr -= sizeof(sljit_ins);+ return inst;+ }++ if (jump->flags & IS_COND) {+ if ((target_addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL)) {+ jump->flags |= PATCH_J;+ inst[0] = (inst[0] & ~(BOFF_X1(-1))) | BOFF_X1(2);+ inst[1] = J_X1;+ return inst + 1;+ }++ return code_ptr;+ }++ if ((target_addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL)) {+ jump->flags |= PATCH_J;++ if (jump->flags & IS_JAL) {+ inst[0] = JAL_X1;++#ifdef TILEGX_JIT_DEBUG+ printf("[runtime relocate]%04d:\t", __LINE__);+ print_insn_tilegx(inst);+#endif++ } else {+ inst[0] = J_X1;++#ifdef TILEGX_JIT_DEBUG+ printf("[runtime relocate]%04d:\t", __LINE__);+ print_insn_tilegx(inst);+#endif+ }++ return inst;+ }++ return code_ptr;+}++SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf;+ sljit_ins *code;+ sljit_ins *code_ptr;+ sljit_ins *buf_ptr;+ sljit_ins *buf_end;+ sljit_uw word_count;+ sljit_uw addr;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));+ reverse_buf(compiler);++ code = (sljit_ins *)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);+ PTR_FAIL_WITH_EXEC_IF(code);+ buf = compiler->buf;++ code_ptr = code;+ word_count = 0;+ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ do {+ buf_ptr = (sljit_ins *)buf->memory;+ buf_end = buf_ptr + (buf->used_size >> 3);+ do {+ *code_ptr = *buf_ptr++;+ SLJIT_ASSERT(!label || label->size >= word_count);+ SLJIT_ASSERT(!jump || jump->addr >= word_count);+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);+ /* These structures are ordered by their address. */+ if (label && label->size == word_count) {+ /* Just recording the address. */+ label->addr = (sljit_uw) code_ptr;+ label->size = code_ptr - code;+ label = label->next;+ }++ if (jump && jump->addr == word_count) {+ if (jump->flags & IS_JAL)+ jump->addr = (sljit_uw)(code_ptr - 4);+ else+ jump->addr = (sljit_uw)(code_ptr - 3);++ code_ptr = detect_jump_type(jump, code_ptr, code);+ jump = jump->next;+ }++ if (const_ && const_->addr == word_count) {+ /* Just recording the address. */+ const_->addr = (sljit_uw) code_ptr;+ const_ = const_->next;+ }++ code_ptr++;+ word_count++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == word_count) {+ label->addr = (sljit_uw) code_ptr;+ label->size = code_ptr - code;+ label = label->next;+ }++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);++ jump = compiler->jumps;+ while (jump) {+ do {+ addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;+ buf_ptr = (sljit_ins *)jump->addr;++ if (jump->flags & PATCH_B) {+ addr = (sljit_sw)(addr - (jump->addr)) >> 3;+ SLJIT_ASSERT((sljit_sw) addr <= SIMM_17BIT_MAX && (sljit_sw) addr >= SIMM_17BIT_MIN);+ buf_ptr[0] = (buf_ptr[0] & ~(BOFF_X1(-1))) | BOFF_X1(addr);++#ifdef TILEGX_JIT_DEBUG+ printf("[runtime relocate]%04d:\t", __LINE__);+ print_insn_tilegx(buf_ptr);+#endif+ break;+ }++ if (jump->flags & PATCH_J) {+ SLJIT_ASSERT((addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL));+ addr = (sljit_sw)(addr - (jump->addr)) >> 3;+ buf_ptr[0] = (buf_ptr[0] & ~(JOFF_X1(-1))) | JOFF_X1(addr);++#ifdef TILEGX_JIT_DEBUG+ printf("[runtime relocate]%04d:\t", __LINE__);+ print_insn_tilegx(buf_ptr);+#endif+ break;+ }++ SLJIT_ASSERT(!(jump->flags & IS_JAL));++ /* Set the fields of immediate loads. */+ buf_ptr[0] = (buf_ptr[0] & ~(0xFFFFL << 43)) | (((addr >> 32) & 0xFFFFL) << 43);+ buf_ptr[1] = (buf_ptr[1] & ~(0xFFFFL << 43)) | (((addr >> 16) & 0xFFFFL) << 43);+ buf_ptr[2] = (buf_ptr[2] & ~(0xFFFFL << 43)) | ((addr & 0xFFFFL) << 43);+ } while (0);++ jump = jump->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);++ SLJIT_CACHE_FLUSH(code, code_ptr);+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);+ return code;+}++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)+{++ if (imm <= SIMM_16BIT_MAX && imm >= SIMM_16BIT_MIN)+ return ADDLI(dst_ar, ZERO, imm);++ if (imm <= SIMM_32BIT_MAX && imm >= SIMM_32BIT_MIN) {+ FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 16));+ return SHL16INSLI(dst_ar, dst_ar, imm);+ }++ if (imm <= SIMM_48BIT_MAX && imm >= SIMM_48BIT_MIN) {+ FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 32));+ FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16));+ return SHL16INSLI(dst_ar, dst_ar, imm);+ }++ FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 48));+ FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 32));+ FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16));+ return SHL16INSLI(dst_ar, dst_ar, imm);+}++static sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm, int flush)+{+ /* Should *not* be optimized as load_immediate, as pcre relocation+ mechanism will match this fixed 4-instruction pattern. */+ if (flush) {+ FAIL_IF(ADDLI_SOLO(dst_ar, ZERO, imm >> 32));+ FAIL_IF(SHL16INSLI_SOLO(dst_ar, dst_ar, imm >> 16));+ return SHL16INSLI_SOLO(dst_ar, dst_ar, imm);+ }++ FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 32));+ FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16));+ return SHL16INSLI(dst_ar, dst_ar, imm);+}++static sljit_s32 emit_const_64(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm, int flush)+{+ /* Should *not* be optimized as load_immediate, as pcre relocation+ mechanism will match this fixed 4-instruction pattern. */+ if (flush) {+ FAIL_IF(ADDLI_SOLO(reg_map[dst_ar], ZERO, imm >> 48));+ FAIL_IF(SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm >> 32));+ FAIL_IF(SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm >> 16));+ return SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm);+ }++ FAIL_IF(ADDLI(reg_map[dst_ar], ZERO, imm >> 48));+ FAIL_IF(SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm >> 32));+ FAIL_IF(SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm >> 16));+ return SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_ins base;+ sljit_s32 i, tmp;+ + CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);+ local_size = (local_size + 7) & ~7;+ compiler->local_size = local_size;++ if (local_size <= SIMM_16BIT_MAX) {+ /* Frequent case. */+ FAIL_IF(ADDLI(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, -local_size));+ base = SLJIT_LOCALS_REG_mapped;+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, local_size));+ FAIL_IF(ADD(TMP_REG2_mapped, SLJIT_LOCALS_REG_mapped, ZERO));+ FAIL_IF(SUB(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped));+ base = TMP_REG2_mapped;+ local_size = 0;+ }++ /* Save the return address. */+ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8));+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, RA, -8));++ /* Save the S registers. */+ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = SLJIT_S0; i >= tmp; i--) {+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8));+ }++ /* Save the R registers that need to be reserved. */+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8));+ }++ /* Move the arguments to S registers. */+ for (i = 0; i < args; i++) {+ FAIL_IF(ADD(reg_map[SLJIT_S0 - i], i, ZERO));+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);++ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);+ compiler->local_size = (local_size + 7) & ~7;++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 local_size;+ sljit_ins base;+ sljit_s32 i, tmp;+ sljit_s32 saveds;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));++ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));++ local_size = compiler->local_size;+ if (local_size <= SIMM_16BIT_MAX)+ base = SLJIT_LOCALS_REG_mapped;+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, local_size));+ FAIL_IF(ADD(TMP_REG1_mapped, SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped));+ base = TMP_REG1_mapped;+ local_size = 0;+ }++ /* Restore the return address. */+ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8));+ FAIL_IF(LD_ADD(RA, ADDR_TMP_mapped, -8));++ /* Restore the S registers. */+ saveds = compiler->saveds;+ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = SLJIT_S0; i >= tmp; i--) {+ FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8));+ }++ /* Restore the R registers that need to be reserved. */+ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8));+ }++ if (compiler->local_size <= SIMM_16BIT_MAX)+ FAIL_IF(ADDLI(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, compiler->local_size));+ else+ FAIL_IF(ADD(SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped, ZERO));++ return JR(RA);+}++/* reg_ar is an absoulute register! */++/* Can perform an operation using at most 1 instruction. */+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)+{+ SLJIT_ASSERT(arg & SLJIT_MEM);++ if ((!(flags & WRITE_BACK) || !(arg & REG_MASK))+ && !(arg & OFFS_REG_MASK) && argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) {+ /* Works for both absoulte and relative addresses. */+ if (SLJIT_UNLIKELY(flags & ARG_TEST))+ return 1;++ FAIL_IF(ADDLI(ADDR_TMP_mapped, reg_map[arg & REG_MASK], argw));++ if (flags & LOAD_DATA)+ FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, ADDR_TMP_mapped));+ else+ FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], ADDR_TMP_mapped, reg_ar));++ return -1;+ }++ return 0;+}++/* See getput_arg below.+ Note: can_cache is called only for binary operators. Those+ operators always uses word arguments without write back. */+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)+{+ SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));++ /* Simple operation except for updates. */+ if (arg & OFFS_REG_MASK) {+ argw &= 0x3;+ next_argw &= 0x3;+ if (argw && argw == next_argw+ && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))+ return 1;+ return 0;+ }++ if (arg == next_arg) {+ if (((next_argw - argw) <= SIMM_16BIT_MAX+ && (next_argw - argw) >= SIMM_16BIT_MIN))+ return 1;++ return 0;+ }++ return 0;+}++/* Emit the necessary instructions. See can_cache above. */+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)+{+ sljit_s32 tmp_ar, base;++ SLJIT_ASSERT(arg & SLJIT_MEM);+ if (!(next_arg & SLJIT_MEM)) {+ next_arg = 0;+ next_argw = 0;+ }++ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA))+ tmp_ar = reg_ar;+ else+ tmp_ar = TMP_REG1_mapped;++ base = arg & REG_MASK;++ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {+ argw &= 0x3;++ if ((flags & WRITE_BACK) && reg_ar == reg_map[base]) {+ SLJIT_ASSERT(!(flags & LOAD_DATA) && reg_map[TMP_REG1] != reg_ar);+ FAIL_IF(ADD(TMP_REG1_mapped, reg_ar, ZERO));+ reg_ar = TMP_REG1_mapped;+ }++ /* Using the cache. */+ if (argw == compiler->cache_argw) {+ if (!(flags & WRITE_BACK)) {+ if (arg == compiler->cache_arg) {+ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);+ }++ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {+ if (arg == next_arg && argw == (next_argw & 0x3)) {+ compiler->cache_arg = arg;+ compiler->cache_argw = argw;+ FAIL_IF(ADD(TMP_REG3_mapped, reg_map[base], TMP_REG3_mapped));+ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);+ }++ FAIL_IF(ADD(tmp_ar, reg_map[base], TMP_REG3_mapped));+ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);+ }+ } else {+ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {+ FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped));+ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar);+ }+ }+ }++ if (SLJIT_UNLIKELY(argw)) {+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);+ compiler->cache_argw = argw;+ FAIL_IF(SHLI(TMP_REG3_mapped, reg_map[OFFS_REG(arg)], argw));+ }++ if (!(flags & WRITE_BACK)) {+ if (arg == next_arg && argw == (next_argw & 0x3)) {+ compiler->cache_arg = arg;+ compiler->cache_argw = argw;+ FAIL_IF(ADD(TMP_REG3_mapped, reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3]));+ tmp_ar = TMP_REG3_mapped;+ } else+ FAIL_IF(ADD(tmp_ar, reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3]));++ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);+ }++ FAIL_IF(ADD(reg_map[base], reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3]));++ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar);+ }++ if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) {+ /* Update only applies if a base register exists. */+ if (reg_ar == reg_map[base]) {+ SLJIT_ASSERT(!(flags & LOAD_DATA) && TMP_REG1_mapped != reg_ar);+ if (argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) {+ FAIL_IF(ADDLI(ADDR_TMP_mapped, reg_map[base], argw));+ if (flags & LOAD_DATA)+ FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, ADDR_TMP_mapped));+ else+ FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], ADDR_TMP_mapped, reg_ar));++ if (argw)+ return ADDLI(reg_map[base], reg_map[base], argw);++ return SLJIT_SUCCESS;+ }++ FAIL_IF(ADD(TMP_REG1_mapped, reg_ar, ZERO));+ reg_ar = TMP_REG1_mapped;+ }++ if (argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) {+ if (argw)+ FAIL_IF(ADDLI(reg_map[base], reg_map[base], argw));+ } else {+ if (compiler->cache_arg == SLJIT_MEM+ && argw - compiler->cache_argw <= SIMM_16BIT_MAX+ && argw - compiler->cache_argw >= SIMM_16BIT_MIN) {+ if (argw != compiler->cache_argw) {+ FAIL_IF(ADD(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw));+ compiler->cache_argw = argw;+ }++ FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped));+ } else {+ compiler->cache_arg = SLJIT_MEM;+ compiler->cache_argw = argw;+ FAIL_IF(load_immediate(compiler, TMP_REG3_mapped, argw));+ FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped));+ }+ }++ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar);+ }++ if (compiler->cache_arg == arg+ && argw - compiler->cache_argw <= SIMM_16BIT_MAX+ && argw - compiler->cache_argw >= SIMM_16BIT_MIN) {+ if (argw != compiler->cache_argw) {+ FAIL_IF(ADDLI(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw));+ compiler->cache_argw = argw;+ }++ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);+ }++ if (compiler->cache_arg == SLJIT_MEM+ && argw - compiler->cache_argw <= SIMM_16BIT_MAX+ && argw - compiler->cache_argw >= SIMM_16BIT_MIN) {+ if (argw != compiler->cache_argw)+ FAIL_IF(ADDLI(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw));+ } else {+ compiler->cache_arg = SLJIT_MEM;+ FAIL_IF(load_immediate(compiler, TMP_REG3_mapped, argw));+ }++ compiler->cache_argw = argw;++ if (!base) {+ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);+ }++ if (arg == next_arg+ && next_argw - argw <= SIMM_16BIT_MAX+ && next_argw - argw >= SIMM_16BIT_MIN) {+ compiler->cache_arg = arg;+ FAIL_IF(ADD(TMP_REG3_mapped, TMP_REG3_mapped, reg_map[base]));+ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);+ }++ FAIL_IF(ADD(tmp_ar, TMP_REG3_mapped, reg_map[base]));++ if (flags & LOAD_DATA)+ return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar);+ else+ return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);+}++static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)+{+ if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))+ return compiler->error;++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+ return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0);+}++static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)+{+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))+ return compiler->error;+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ /* For UNUSED dst. Uncommon, but possible. */+ if (dst == SLJIT_UNUSED)+ return SLJIT_SUCCESS;++ if (FAST_IS_REG(dst))+ return ADD(reg_map[dst], RA, ZERO);++ /* Memory. */+ return emit_op_mem(compiler, WORD_DATA, RA, dst, dstw);+}++static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2)+{+ sljit_s32 overflow_ra = 0;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if (dst != src2)+ return ADD(reg_map[dst], reg_map[src2], ZERO);+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S32)+ return BFEXTS(reg_map[dst], reg_map[src2], 0, 31);++ return BFEXTU(reg_map[dst], reg_map[src2], 0, 31);+ } else if (dst != src2) {+ SLJIT_ASSERT(src2 == 0);+ return ADD(reg_map[dst], reg_map[src2], ZERO);+ }++ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S8)+ return BFEXTS(reg_map[dst], reg_map[src2], 0, 7);++ return BFEXTU(reg_map[dst], reg_map[src2], 0, 7);+ } else if (dst != src2) {+ SLJIT_ASSERT(src2 == 0);+ return ADD(reg_map[dst], reg_map[src2], ZERO);+ }++ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S16)+ return BFEXTS(reg_map[dst], reg_map[src2], 0, 15);++ return BFEXTU(reg_map[dst], reg_map[src2], 0, 15);+ } else if (dst != src2) {+ SLJIT_ASSERT(src2 == 0);+ return ADD(reg_map[dst], reg_map[src2], ZERO);+ }++ return SLJIT_SUCCESS;++ case SLJIT_NOT:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if (op & SLJIT_SET_E)+ FAIL_IF(NOR(EQUAL_FLAG, reg_map[src2], reg_map[src2]));+ if (CHECK_FLAGS(SLJIT_SET_E))+ FAIL_IF(NOR(reg_map[dst], reg_map[src2], reg_map[src2]));++ return SLJIT_SUCCESS;++ case SLJIT_CLZ:+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));+ if (op & SLJIT_SET_E)+ FAIL_IF(CLZ(EQUAL_FLAG, reg_map[src2]));+ if (CHECK_FLAGS(SLJIT_SET_E))+ FAIL_IF(CLZ(reg_map[dst], reg_map[src2]));++ return SLJIT_SUCCESS;++ case SLJIT_ADD:+ if (flags & SRC2_IMM) {+ if (op & SLJIT_SET_O) {+ FAIL_IF(SHRUI(TMP_EREG1, reg_map[src1], 63));+ if (src2 < 0)+ FAIL_IF(XORI(TMP_EREG1, TMP_EREG1, 1));+ }++ if (op & SLJIT_SET_E)+ FAIL_IF(ADDLI(EQUAL_FLAG, reg_map[src1], src2));++ if (op & SLJIT_SET_C) {+ if (src2 >= 0)+ FAIL_IF(ORI(ULESS_FLAG ,reg_map[src1], src2));+ else {+ FAIL_IF(ADDLI(ULESS_FLAG ,ZERO, src2));+ FAIL_IF(OR(ULESS_FLAG,reg_map[src1],ULESS_FLAG));+ }+ }++ /* dst may be the same as src1 or src2. */+ if (CHECK_FLAGS(SLJIT_SET_E))+ FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], src2));++ if (op & SLJIT_SET_O) {+ FAIL_IF(SHRUI(OVERFLOW_FLAG, reg_map[dst], 63));++ if (src2 < 0)+ FAIL_IF(XORI(OVERFLOW_FLAG, OVERFLOW_FLAG, 1));+ }+ } else {+ if (op & SLJIT_SET_O) {+ FAIL_IF(XOR(TMP_EREG1, reg_map[src1], reg_map[src2]));+ FAIL_IF(SHRUI(TMP_EREG1, TMP_EREG1, 63));++ if (src1 != dst)+ overflow_ra = reg_map[src1];+ else if (src2 != dst)+ overflow_ra = reg_map[src2];+ else {+ /* Rare ocasion. */+ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));+ overflow_ra = TMP_EREG2;+ }+ }++ if (op & SLJIT_SET_E)+ FAIL_IF(ADD(EQUAL_FLAG ,reg_map[src1], reg_map[src2]));++ if (op & SLJIT_SET_C)+ FAIL_IF(OR(ULESS_FLAG,reg_map[src1], reg_map[src2]));++ /* dst may be the same as src1 or src2. */+ if (CHECK_FLAGS(SLJIT_SET_E))+ FAIL_IF(ADD(reg_map[dst],reg_map[src1], reg_map[src2]));++ if (op & SLJIT_SET_O) {+ FAIL_IF(XOR(OVERFLOW_FLAG,reg_map[dst], overflow_ra));+ FAIL_IF(SHRUI(OVERFLOW_FLAG, OVERFLOW_FLAG, 63));+ }+ }++ /* a + b >= a | b (otherwise, the carry should be set to 1). */+ if (op & SLJIT_SET_C)+ FAIL_IF(CMPLTU(ULESS_FLAG ,reg_map[dst] ,ULESS_FLAG));++ if (op & SLJIT_SET_O)+ return CMOVNEZ(OVERFLOW_FLAG, TMP_EREG1, ZERO);++ return SLJIT_SUCCESS;++ case SLJIT_ADDC:+ if (flags & SRC2_IMM) {+ if (op & SLJIT_SET_C) {+ if (src2 >= 0)+ FAIL_IF(ORI(TMP_EREG1, reg_map[src1], src2));+ else {+ FAIL_IF(ADDLI(TMP_EREG1, ZERO, src2));+ FAIL_IF(OR(TMP_EREG1, reg_map[src1], TMP_EREG1));+ }+ }++ FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], src2));++ } else {+ if (op & SLJIT_SET_C)+ FAIL_IF(OR(TMP_EREG1, reg_map[src1], reg_map[src2]));++ /* dst may be the same as src1 or src2. */+ FAIL_IF(ADD(reg_map[dst], reg_map[src1], reg_map[src2]));+ }++ if (op & SLJIT_SET_C)+ FAIL_IF(CMPLTU(TMP_EREG1, reg_map[dst], TMP_EREG1));++ FAIL_IF(ADD(reg_map[dst], reg_map[dst], ULESS_FLAG));++ if (!(op & SLJIT_SET_C))+ return SLJIT_SUCCESS;++ /* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */+ FAIL_IF(CMPLTUI(TMP_EREG2, reg_map[dst], 1));+ FAIL_IF(AND(TMP_EREG2, TMP_EREG2, ULESS_FLAG));+ /* Set carry flag. */+ return OR(ULESS_FLAG, TMP_EREG2, TMP_EREG1);++ case SLJIT_SUB:+ if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_16BIT_MIN)) {+ FAIL_IF(ADDLI(TMP_REG2_mapped, ZERO, src2));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ if (flags & SRC2_IMM) {+ if (op & SLJIT_SET_O) {+ FAIL_IF(SHRUI(TMP_EREG1,reg_map[src1], 63));++ if (src2 < 0)+ FAIL_IF(XORI(TMP_EREG1, TMP_EREG1, 1));++ if (src1 != dst)+ overflow_ra = reg_map[src1];+ else {+ /* Rare ocasion. */+ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));+ overflow_ra = TMP_EREG2;+ }+ }++ if (op & SLJIT_SET_E)+ FAIL_IF(ADDLI(EQUAL_FLAG, reg_map[src1], -src2));++ if (op & SLJIT_SET_C) {+ FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2));+ FAIL_IF(CMPLTU(ULESS_FLAG, reg_map[src1], ADDR_TMP_mapped));+ }++ /* dst may be the same as src1 or src2. */+ if (CHECK_FLAGS(SLJIT_SET_E))+ FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], -src2));++ } else {++ if (op & SLJIT_SET_O) {+ FAIL_IF(XOR(TMP_EREG1, reg_map[src1], reg_map[src2]));+ FAIL_IF(SHRUI(TMP_EREG1, TMP_EREG1, 63));++ if (src1 != dst)+ overflow_ra = reg_map[src1];+ else {+ /* Rare ocasion. */+ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));+ overflow_ra = TMP_EREG2;+ }+ }++ if (op & SLJIT_SET_E)+ FAIL_IF(SUB(EQUAL_FLAG, reg_map[src1], reg_map[src2]));++ if (op & (SLJIT_SET_U | SLJIT_SET_C))+ FAIL_IF(CMPLTU(ULESS_FLAG, reg_map[src1], reg_map[src2]));++ if (op & SLJIT_SET_U)+ FAIL_IF(CMPLTU(UGREATER_FLAG, reg_map[src2], reg_map[src1]));++ if (op & SLJIT_SET_S) {+ FAIL_IF(CMPLTS(LESS_FLAG ,reg_map[src1] ,reg_map[src2]));+ FAIL_IF(CMPLTS(GREATER_FLAG ,reg_map[src2] ,reg_map[src1]));+ }++ /* dst may be the same as src1 or src2. */+ if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))+ FAIL_IF(SUB(reg_map[dst], reg_map[src1], reg_map[src2]));+ }++ if (op & SLJIT_SET_O) {+ FAIL_IF(XOR(OVERFLOW_FLAG, reg_map[dst], overflow_ra));+ FAIL_IF(SHRUI(OVERFLOW_FLAG, OVERFLOW_FLAG, 63));+ return CMOVEQZ(OVERFLOW_FLAG, TMP_EREG1, ZERO);+ }++ return SLJIT_SUCCESS;++ case SLJIT_SUBC:+ if ((flags & SRC2_IMM) && src2 == SIMM_16BIT_MIN) {+ FAIL_IF(ADDLI(TMP_REG2_mapped, ZERO, src2));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ if (flags & SRC2_IMM) {+ if (op & SLJIT_SET_C) {+ FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, -src2));+ FAIL_IF(CMPLTU(TMP_EREG1, reg_map[src1], ADDR_TMP_mapped));+ }++ /* dst may be the same as src1 or src2. */+ FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], -src2));++ } else {+ if (op & SLJIT_SET_C)+ FAIL_IF(CMPLTU(TMP_EREG1, reg_map[src1], reg_map[src2]));+ /* dst may be the same as src1 or src2. */+ FAIL_IF(SUB(reg_map[dst], reg_map[src1], reg_map[src2]));+ }++ if (op & SLJIT_SET_C)+ FAIL_IF(CMOVEQZ(TMP_EREG1, reg_map[dst], ULESS_FLAG));++ FAIL_IF(SUB(reg_map[dst], reg_map[dst], ULESS_FLAG));++ if (op & SLJIT_SET_C)+ FAIL_IF(ADD(ULESS_FLAG, TMP_EREG1, ZERO));++ return SLJIT_SUCCESS;++ case SLJIT_MUL:+ if (flags & SRC2_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG2_mapped, src2));+ src2 = TMP_REG2;+ flags &= ~SRC2_IMM;+ }++ FAIL_IF(MUL(reg_map[dst], reg_map[src1], reg_map[src2]));++ return SLJIT_SUCCESS;++#define EMIT_LOGICAL(op_imm, op_norm) \+ if (flags & SRC2_IMM) { \+ FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); \+ if (op & SLJIT_SET_E) \+ FAIL_IF(push_3_buffer( \+ compiler, op_norm, EQUAL_FLAG, reg_map[src1], \+ ADDR_TMP_mapped, __LINE__)); \+ if (CHECK_FLAGS(SLJIT_SET_E)) \+ FAIL_IF(push_3_buffer( \+ compiler, op_norm, reg_map[dst], reg_map[src1], \+ ADDR_TMP_mapped, __LINE__)); \+ } else { \+ if (op & SLJIT_SET_E) \+ FAIL_IF(push_3_buffer( \+ compiler, op_norm, EQUAL_FLAG, reg_map[src1], \+ reg_map[src2], __LINE__)); \+ if (CHECK_FLAGS(SLJIT_SET_E)) \+ FAIL_IF(push_3_buffer( \+ compiler, op_norm, reg_map[dst], reg_map[src1], \+ reg_map[src2], __LINE__)); \+ }++ case SLJIT_AND:+ EMIT_LOGICAL(TILEGX_OPC_ANDI, TILEGX_OPC_AND);+ return SLJIT_SUCCESS;++ case SLJIT_OR:+ EMIT_LOGICAL(TILEGX_OPC_ORI, TILEGX_OPC_OR);+ return SLJIT_SUCCESS;++ case SLJIT_XOR:+ EMIT_LOGICAL(TILEGX_OPC_XORI, TILEGX_OPC_XOR);+ return SLJIT_SUCCESS;++#define EMIT_SHIFT(op_imm, op_norm) \+ if (flags & SRC2_IMM) { \+ if (op & SLJIT_SET_E) \+ FAIL_IF(push_3_buffer( \+ compiler, op_imm, EQUAL_FLAG, reg_map[src1], \+ src2 & 0x3F, __LINE__)); \+ if (CHECK_FLAGS(SLJIT_SET_E)) \+ FAIL_IF(push_3_buffer( \+ compiler, op_imm, reg_map[dst], reg_map[src1], \+ src2 & 0x3F, __LINE__)); \+ } else { \+ if (op & SLJIT_SET_E) \+ FAIL_IF(push_3_buffer( \+ compiler, op_norm, EQUAL_FLAG, reg_map[src1], \+ reg_map[src2], __LINE__)); \+ if (CHECK_FLAGS(SLJIT_SET_E)) \+ FAIL_IF(push_3_buffer( \+ compiler, op_norm, reg_map[dst], reg_map[src1], \+ reg_map[src2], __LINE__)); \+ }++ case SLJIT_SHL:+ EMIT_SHIFT(TILEGX_OPC_SHLI, TILEGX_OPC_SHL);+ return SLJIT_SUCCESS;++ case SLJIT_LSHR:+ EMIT_SHIFT(TILEGX_OPC_SHRUI, TILEGX_OPC_SHRU);+ return SLJIT_SUCCESS;++ case SLJIT_ASHR:+ EMIT_SHIFT(TILEGX_OPC_SHRSI, TILEGX_OPC_SHRS);+ return SLJIT_SUCCESS;+ }++ SLJIT_UNREACHABLE();+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)+{+ /* arg1 goes to TMP_REG1 or src reg.+ arg2 goes to TMP_REG2, imm or src reg.+ TMP_REG3 can be used for caching.+ result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */+ sljit_s32 dst_r = TMP_REG2;+ sljit_s32 src1_r;+ sljit_sw src2_r = 0;+ sljit_s32 sugg_src2_r = TMP_REG2;++ if (!(flags & ALT_KEEP_CACHE)) {+ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+ }++ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM))+ return SLJIT_SUCCESS;+ if (GET_FLAGS(op))+ flags |= UNUSED_DEST;+ } else if (FAST_IS_REG(dst)) {+ dst_r = dst;+ flags |= REG_DEST;+ if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)+ sugg_src2_r = dst_r;+ } else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1_mapped, dst, dstw))+ flags |= SLOW_DEST;++ if (flags & IMM_OP) {+ if ((src2 & SLJIT_IMM) && src2w) {+ if ((!(flags & LOGICAL_OP)+ && (src2w <= SIMM_16BIT_MAX && src2w >= SIMM_16BIT_MIN))+ || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_16BIT_MAX))) {+ flags |= SRC2_IMM;+ src2_r = src2w;+ }+ }++ if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {+ if ((!(flags & LOGICAL_OP)+ && (src1w <= SIMM_16BIT_MAX && src1w >= SIMM_16BIT_MIN))+ || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_16BIT_MAX))) {+ flags |= SRC2_IMM;+ src2_r = src1w;++ /* And swap arguments. */+ src1 = src2;+ src1w = src2w;+ src2 = SLJIT_IMM;+ /* src2w = src2_r unneeded. */+ }+ }+ }++ /* Source 1. */+ if (FAST_IS_REG(src1)) {+ src1_r = src1;+ flags |= REG1_SOURCE;+ } else if (src1 & SLJIT_IMM) {+ if (src1w) {+ FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, src1w));+ src1_r = TMP_REG1;+ } else+ src1_r = 0;+ } else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC1;+ src1_r = TMP_REG1;+ }++ /* Source 2. */+ if (FAST_IS_REG(src2)) {+ src2_r = src2;+ flags |= REG2_SOURCE;+ if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)+ dst_r = src2_r;+ } else if (src2 & SLJIT_IMM) {+ if (!(flags & SRC2_IMM)) {+ if (src2w) {+ FAIL_IF(load_immediate(compiler, reg_map[sugg_src2_r], src2w));+ src2_r = sugg_src2_r;+ } else {+ src2_r = 0;+ if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM))+ dst_r = 0;+ }+ }+ } else {+ if (getput_arg_fast(compiler, flags | LOAD_DATA, reg_map[sugg_src2_r], src2, src2w))+ FAIL_IF(compiler->error);+ else+ flags |= SLOW_SRC2;+ src2_r = sugg_src2_r;+ }++ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {+ SLJIT_ASSERT(src2_r == TMP_REG2);+ if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2_mapped, src2, src2w, src1, src1w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, dst, dstw));+ } else {+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, src2, src2w));+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2_mapped, src2, src2w, dst, dstw));+ }+ } else if (flags & SLOW_SRC1)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, dst, dstw));+ else if (flags & SLOW_SRC2)+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, reg_map[sugg_src2_r], src2, src2w, dst, dstw));++ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));++ if (dst & SLJIT_MEM) {+ if (!(flags & SLOW_DEST)) {+ getput_arg_fast(compiler, flags, reg_map[dst_r], dst, dstw);+ return compiler->error;+ }++ return getput_arg(compiler, flags, reg_map[dst_r], dst, dstw, 0, 0);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw, sljit_s32 type)+{+ sljit_s32 sugg_dst_ar, dst_ar;+ sljit_s32 flags = GET_ALL_FLAGS(op);+ sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ op = GET_OPCODE(op);+ if (op == SLJIT_MOV_S32 || op == SLJIT_MOV_U32)+ mem_type = INT_DATA | SIGNED_DATA;+ sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2];++ compiler->cache_arg = 0;+ compiler->cache_argw = 0;+ if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw));+ src = TMP_REG1;+ srcw = 0;+ }++ switch (type & 0xff) {+ case SLJIT_EQUAL:+ case SLJIT_NOT_EQUAL:+ FAIL_IF(CMPLTUI(sugg_dst_ar, EQUAL_FLAG, 1));+ dst_ar = sugg_dst_ar;+ break;+ case SLJIT_LESS:+ case SLJIT_GREATER_EQUAL:+ dst_ar = ULESS_FLAG;+ break;+ case SLJIT_GREATER:+ case SLJIT_LESS_EQUAL:+ dst_ar = UGREATER_FLAG;+ break;+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_GREATER_EQUAL:+ dst_ar = LESS_FLAG;+ break;+ case SLJIT_SIG_GREATER:+ case SLJIT_SIG_LESS_EQUAL:+ dst_ar = GREATER_FLAG;+ break;+ case SLJIT_OVERFLOW:+ case SLJIT_NOT_OVERFLOW:+ dst_ar = OVERFLOW_FLAG;+ break;+ case SLJIT_MUL_OVERFLOW:+ case SLJIT_MUL_NOT_OVERFLOW:+ FAIL_IF(CMPLTUI(sugg_dst_ar, OVERFLOW_FLAG, 1));+ dst_ar = sugg_dst_ar;+ type ^= 0x1; /* Flip type bit for the XORI below. */+ break;++ default:+ SLJIT_UNREACHABLE();+ dst_ar = sugg_dst_ar;+ break;+ }++ if (type & 0x1) {+ FAIL_IF(XORI(sugg_dst_ar, dst_ar, 1));+ dst_ar = sugg_dst_ar;+ }++ if (op >= SLJIT_ADD) {+ if (TMP_REG2_mapped != dst_ar)+ FAIL_IF(ADD(TMP_REG2_mapped, dst_ar, ZERO));+ return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw);++ if (sugg_dst_ar != dst_ar)+ return ADD(sugg_dst_ar, dst_ar, ZERO);++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) {+ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ op = GET_OPCODE(op);+ switch (op) {+ case SLJIT_NOP:+ return push_0_buffer(compiler, TILEGX_OPC_FNOP, __LINE__);++ case SLJIT_BREAKPOINT:+ return PI(BPT);++ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIVMOD_SW:+ case SLJIT_DIV_UW:+ case SLJIT_DIV_SW:+ SLJIT_UNREACHABLE();+ case SLJIT_ENDBR:+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOV_U32:+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOV_S32:+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOV_U8:+ return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8) srcw : srcw);++ case SLJIT_MOV_S8:+ return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8) srcw : srcw);++ case SLJIT_MOV_U16:+ return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16) srcw : srcw);++ case SLJIT_MOV_S16:+ return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16) srcw : srcw);++ case SLJIT_MOVU:+ case SLJIT_MOVU_P:+ return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOVU_U32:+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOVU_S32:+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_MOVU_U8:+ return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8) srcw : srcw);++ case SLJIT_MOVU_S8:+ return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8) srcw : srcw);++ case SLJIT_MOVU_U16:+ return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16) srcw : srcw);++ case SLJIT_MOVU_S16:+ return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16) srcw : srcw);++ case SLJIT_NOT:+ return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);++ case SLJIT_NEG:+ return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);++ case SLJIT_CLZ:+ return emit_op(compiler, op, (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ case SLJIT_ADDC:+ return emit_op(compiler, op, CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SUB:+ case SLJIT_SUBC:+ return emit_op(compiler, op, IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_MUL:+ return emit_op(compiler, op, CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_AND:+ case SLJIT_OR:+ case SLJIT_XOR:+ return emit_op(compiler, op, CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);++ case SLJIT_SHL:+ case SLJIT_LSHR:+ case SLJIT_ASHR:+ if (src2 & SLJIT_IMM)+ src2w &= 0x3f;+ if (op & SLJIT_I32_OP)+ src2w &= 0x1f;++ return emit_op(compiler, op, IMM_OP, dst, dstw, src1, src1w, src2, src2w);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src))+ FAIL_IF(ADD(RA, reg_map[src], ZERO));++ else+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RA, src, srcw));++ return JR(RA);+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ return SLJIT_SUCCESS;+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_compiler *compiler)+{+ struct sljit_label *label;++ flush_buffer(compiler);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label *)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);+ return label;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 src_r = TMP_REG2;+ struct sljit_jump *jump = NULL;++ flush_buffer(compiler);++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ if (FAST_IS_REG(src)) {+ if (reg_map[src] != 0)+ src_r = src;+ else+ FAIL_IF(ADD_SOLO(TMP_REG2_mapped, reg_map[src], ZERO));+ }++ if (type >= SLJIT_CALL0) {+ SLJIT_ASSERT(reg_map[PIC_ADDR_REG] == 16 && PIC_ADDR_REG == TMP_REG2);+ if (src & (SLJIT_IMM | SLJIT_MEM)) {+ if (src & SLJIT_IMM)+ FAIL_IF(emit_const(compiler, reg_map[PIC_ADDR_REG], srcw, 1));+ else {+ SLJIT_ASSERT(src_r == TMP_REG2 && (src & SLJIT_MEM));+ FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));+ }++ FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO));++ FAIL_IF(ADDI_SOLO(54, 54, -16));++ FAIL_IF(JALR_SOLO(reg_map[PIC_ADDR_REG]));++ return ADDI_SOLO(54, 54, 16);+ }++ /* Register input. */+ if (type >= SLJIT_CALL1)+ FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO));++ FAIL_IF(ADD_SOLO(reg_map[PIC_ADDR_REG], reg_map[src_r], ZERO));++ FAIL_IF(ADDI_SOLO(54, 54, -16));++ FAIL_IF(JALR_SOLO(reg_map[src_r]));++ return ADDI_SOLO(54, 54, 16);+ }++ if (src & SLJIT_IMM) {+ jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));+ jump->u.target = srcw;+ FAIL_IF(emit_const(compiler, TMP_REG2_mapped, 0, 1));++ if (type >= SLJIT_FAST_CALL) {+ FAIL_IF(ADD_SOLO(ZERO, ZERO, ZERO));+ jump->addr = compiler->size;+ FAIL_IF(JR_SOLO(reg_map[src_r]));+ } else {+ jump->addr = compiler->size;+ FAIL_IF(JR_SOLO(reg_map[src_r]));+ }++ return SLJIT_SUCCESS;++ } else if (src & SLJIT_MEM) {+ FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));+ flush_buffer(compiler);+ }++ FAIL_IF(JR_SOLO(reg_map[src_r]));++ if (jump)+ jump->addr = compiler->size;++ return SLJIT_SUCCESS;+}++#define BR_Z(src) \+ inst = BEQZ_X1 | SRCA_X1(src); \+ flags = IS_COND;++#define BR_NZ(src) \+ inst = BNEZ_X1 | SRCA_X1(src); \+ flags = IS_COND;++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ struct sljit_jump *jump;+ sljit_ins inst;+ sljit_s32 flags = 0;++ flush_buffer(compiler);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);+ type &= 0xff;++ switch (type) {+ case SLJIT_EQUAL:+ BR_NZ(EQUAL_FLAG);+ break;+ case SLJIT_NOT_EQUAL:+ BR_Z(EQUAL_FLAG);+ break;+ case SLJIT_LESS:+ BR_Z(ULESS_FLAG);+ break;+ case SLJIT_GREATER_EQUAL:+ BR_NZ(ULESS_FLAG);+ break;+ case SLJIT_GREATER:+ BR_Z(UGREATER_FLAG);+ break;+ case SLJIT_LESS_EQUAL:+ BR_NZ(UGREATER_FLAG);+ break;+ case SLJIT_SIG_LESS:+ BR_Z(LESS_FLAG);+ break;+ case SLJIT_SIG_GREATER_EQUAL:+ BR_NZ(LESS_FLAG);+ break;+ case SLJIT_SIG_GREATER:+ BR_Z(GREATER_FLAG);+ break;+ case SLJIT_SIG_LESS_EQUAL:+ BR_NZ(GREATER_FLAG);+ break;+ case SLJIT_OVERFLOW:+ case SLJIT_MUL_OVERFLOW:+ BR_Z(OVERFLOW_FLAG);+ break;+ case SLJIT_NOT_OVERFLOW:+ case SLJIT_MUL_NOT_OVERFLOW:+ BR_NZ(OVERFLOW_FLAG);+ break;+ default:+ /* Not conditional branch. */+ inst = 0;+ break;+ }++ jump->flags |= flags;++ if (inst) {+ inst = inst | ((type <= SLJIT_JUMP) ? BOFF_X1(5) : BOFF_X1(6));+ PTR_FAIL_IF(PI(inst));+ }++ PTR_FAIL_IF(emit_const(compiler, TMP_REG2_mapped, 0, 1));+ if (type <= SLJIT_JUMP) {+ jump->addr = compiler->size;+ PTR_FAIL_IF(JR_SOLO(TMP_REG2_mapped));+ } else {+ SLJIT_ASSERT(reg_map[PIC_ADDR_REG] == 16 && PIC_ADDR_REG == TMP_REG2);+ /* Cannot be optimized out if type is >= CALL0. */+ jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? SLJIT_REWRITABLE_JUMP : 0);+ PTR_FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO));+ jump->addr = compiler->size;+ PTR_FAIL_IF(JALR_SOLO(TMP_REG2_mapped));+ }++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)+{+ SLJIT_UNREACHABLE();+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)+{+ SLJIT_UNREACHABLE();+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 reg;++ flush_buffer(compiler);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ const_ = (struct sljit_const *)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ reg = FAST_IS_REG(dst) ? dst : TMP_REG2;++ PTR_FAIL_IF(emit_const_64(compiler, reg, init_value, 1));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));+ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target)+{+ sljit_ins *inst = (sljit_ins *)addr;++ inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_target >> 32) & 0xffff) << 43);+ inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_target >> 16) & 0xffff) << 43);+ inst[2] = (inst[2] & ~(0xFFFFL << 43)) | ((new_target & 0xffff) << 43);+ SLJIT_CACHE_FLUSH(inst, inst + 3);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)+{+ sljit_ins *inst = (sljit_ins *)addr;++ inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_constant >> 48) & 0xFFFFL) << 43);+ inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_constant >> 32) & 0xFFFFL) << 43);+ inst[2] = (inst[2] & ~(0xFFFFL << 43)) | (((new_constant >> 16) & 0xFFFFL) << 43);+ inst[3] = (inst[3] & ~(0xFFFFL << 43)) | ((new_constant & 0xFFFFL) << 43);+ SLJIT_CACHE_FLUSH(inst, inst + 4);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(reg));+ return reg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));+ return SLJIT_ERR_UNSUPPORTED;+}+
+ src/c/pcre2/src/sljit/sljitNativeX86_32.c view
@@ -0,0 +1,928 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/* x86 32-bit arch dependent functions. */++static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_sw imm)+{+ sljit_u8 *inst;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));+ FAIL_IF(!inst);+ INC_SIZE(1 + sizeof(sljit_sw));+ *inst++ = opcode;+ sljit_unaligned_store_sw(inst, imm);+ return SLJIT_SUCCESS;+}++static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset)+{+ sljit_s32 type = jump->flags >> TYPE_SHIFT;++ if (type == SLJIT_JUMP) {+ *code_ptr++ = JMP_i32;+ jump->addr++;+ }+ else if (type >= SLJIT_FAST_CALL) {+ *code_ptr++ = CALL_i32;+ jump->addr++;+ }+ else {+ *code_ptr++ = GROUP_0F;+ *code_ptr++ = get_jump_code(type);+ jump->addr += 2;+ }++ if (jump->flags & JUMP_LABEL)+ jump->flags |= PATCH_MW;+ else+ sljit_unaligned_store_sw(code_ptr, jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset);+ code_ptr += 4;++ return code_ptr;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 args, size;+ sljit_u8 *inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ /* Emit ENDBR32 at function entry if needed. */+ FAIL_IF(emit_endbranch(compiler));++ args = get_arg_count(arg_types);+ compiler->args = args;++ /* [esp+0] for saving temporaries and function calls. */+ compiler->stack_tmp_size = 2 * sizeof(sljit_sw);++#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ if (scratches > 3)+ compiler->stack_tmp_size = 3 * sizeof(sljit_sw);+#endif++ compiler->saveds_offset = compiler->stack_tmp_size;+ if (scratches > 3)+ compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);++ compiler->locals_offset = compiler->saveds_offset;++ if (saveds > 3)+ compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw);++ if (options & SLJIT_F64_ALIGNMENT)+ compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1);++ size = 1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3);+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ size += (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);+#else+ size += (args > 0 ? (2 + args * 3) : 0);+#endif+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);++ INC_SIZE(size);+ PUSH_REG(reg_map[TMP_REG1]);+#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ if (args > 0) {+ *inst++ = MOV_r_rm;+ *inst++ = MOD_REG | (reg_map[TMP_REG1] << 3) | 0x4 /* esp */;+ }+#endif+ if (saveds > 2 || scratches > 9)+ PUSH_REG(reg_map[SLJIT_S2]);+ if (saveds > 1 || scratches > 10)+ PUSH_REG(reg_map[SLJIT_S1]);+ if (saveds > 0 || scratches > 11)+ PUSH_REG(reg_map[SLJIT_S0]);++#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ if (args > 0) {+ inst[0] = MOV_r_rm;+ inst[1] = MOD_REG | (reg_map[SLJIT_S0] << 3) | reg_map[SLJIT_R2];+ inst += 2;+ }+ if (args > 1) {+ inst[0] = MOV_r_rm;+ inst[1] = MOD_REG | (reg_map[SLJIT_S1] << 3) | reg_map[SLJIT_R1];+ inst += 2;+ }+ if (args > 2) {+ inst[0] = MOV_r_rm;+ inst[1] = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | 0x4 /* esp */;+ inst[2] = 0x24;+ inst[3] = sizeof(sljit_sw) * (3 + 2); /* saveds >= 3 as well. */+ }+#else+ if (args > 0) {+ inst[0] = MOV_r_rm;+ inst[1] = MOD_DISP8 | (reg_map[SLJIT_S0] << 3) | reg_map[TMP_REG1];+ inst[2] = sizeof(sljit_sw) * 2;+ inst += 3;+ }+ if (args > 1) {+ inst[0] = MOV_r_rm;+ inst[1] = MOD_DISP8 | (reg_map[SLJIT_S1] << 3) | reg_map[TMP_REG1];+ inst[2] = sizeof(sljit_sw) * 3;+ inst += 3;+ }+ if (args > 2) {+ inst[0] = MOV_r_rm;+ inst[1] = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | reg_map[TMP_REG1];+ inst[2] = sizeof(sljit_sw) * 4;+ }+#endif++ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0);++#if defined(__APPLE__)+ /* Ignore pushed registers and SLJIT_LOCALS_OFFSET when computing the aligned local size. */+ saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);+ local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;+#else+ if (options & SLJIT_F64_ALIGNMENT)+ local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1));+ else+ local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1));+#endif++ compiler->local_size = local_size;++#ifdef _WIN32+ if (local_size > 0) {+ if (local_size <= 4 * 4096) {+ if (local_size > 4096)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096);+ if (local_size > 2 * 4096)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);+ if (local_size > 3 * 4096)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);+ }+ else {+ EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_SP, 0);+ EMIT_MOV(compiler, SLJIT_R1, 0, SLJIT_IMM, (local_size - 1) >> 12);++ SLJIT_ASSERT (reg_map[SLJIT_R0] == 0);++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_R0), -4096);+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4096));+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1));++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);++ INC_SIZE(2);+ inst[0] = JNE_i8;+ inst[1] = (sljit_s8) -16;+ }++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size);+ }+#endif++ SLJIT_ASSERT(local_size > 0);++#if !defined(__APPLE__)+ if (options & SLJIT_F64_ALIGNMENT) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SP, 0);++ /* Some space might allocated during sljit_grow_stack() above on WIN32. */+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size + sizeof(sljit_sw)));++#if defined _WIN32 && !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ if (compiler->local_size > 1024)+ FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),+ TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, sizeof(sljit_sw)));+#endif++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 6);+ FAIL_IF(!inst);++ INC_SIZE(6);+ inst[0] = GROUP_BINARY_81;+ inst[1] = MOD_REG | AND | reg_map[SLJIT_SP];+ sljit_unaligned_store_sw(inst + 2, ~(sizeof(sljit_f64) - 1));++ /* The real local size must be used. */+ return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), compiler->local_size, TMP_REG1, 0);+ }+#endif+ return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ compiler->args = get_arg_count(arg_types);++ /* [esp+0] for saving temporaries and function calls. */+ compiler->stack_tmp_size = 2 * sizeof(sljit_sw);++#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ if (scratches > 3)+ compiler->stack_tmp_size = 3 * sizeof(sljit_sw);+#endif++ compiler->saveds_offset = compiler->stack_tmp_size;+ if (scratches > 3)+ compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);++ compiler->locals_offset = compiler->saveds_offset;++ if (saveds > 3)+ compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw);++ if (options & SLJIT_F64_ALIGNMENT)+ compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1);++#if defined(__APPLE__)+ saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);+ compiler->local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;+#else+ if (options & SLJIT_F64_ALIGNMENT)+ compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1));+ else+ compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1));+#endif+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 size;+ sljit_u8 *inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));+ SLJIT_ASSERT(compiler->args >= 0);++ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));++ SLJIT_ASSERT(compiler->local_size > 0);++#if !defined(__APPLE__)+ if (compiler->options & SLJIT_F64_ALIGNMENT)+ EMIT_MOV(compiler, SLJIT_SP, 0, SLJIT_MEM1(SLJIT_SP), compiler->local_size)+ else+ FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));+#else+ FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));+#endif++ size = 2 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) ++ (compiler->saveds <= 3 ? compiler->saveds : 3);+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ if (compiler->args > 2)+ size += 2;+#endif+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);++ INC_SIZE(size);++ if (compiler->saveds > 0 || compiler->scratches > 11)+ POP_REG(reg_map[SLJIT_S0]);+ if (compiler->saveds > 1 || compiler->scratches > 10)+ POP_REG(reg_map[SLJIT_S1]);+ if (compiler->saveds > 2 || compiler->scratches > 9)+ POP_REG(reg_map[SLJIT_S2]);+ POP_REG(reg_map[TMP_REG1]);+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ if (compiler->args > 2)+ RET_I16(sizeof(sljit_sw));+ else+ RET();+#else+ RET();+#endif++ return SLJIT_SUCCESS;+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++/* Size contains the flags as well. */+static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size,+ /* The register or immediate operand. */+ sljit_s32 a, sljit_sw imma,+ /* The general operand (not immediate). */+ sljit_s32 b, sljit_sw immb)+{+ sljit_u8 *inst;+ sljit_u8 *buf_ptr;+ sljit_s32 flags = size & ~0xf;+ sljit_s32 inst_size;++ /* Both cannot be switched on. */+ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));+ /* Size flags not allowed for typed instructions. */+ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);+ /* Both size flags cannot be switched on. */+ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));+ /* SSE2 and immediate is not possible. */+ SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));+ SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)+ && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)+ && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));+ /* We don't support (%ebp). */+ SLJIT_ASSERT(!(b & SLJIT_MEM) || immb || reg_map[b & REG_MASK] != 5);++ size &= 0xf;+ inst_size = size;++ if (flags & (EX86_PREF_F2 | EX86_PREF_F3))+ inst_size++;+ if (flags & EX86_PREF_66)+ inst_size++;++ /* Calculate size of b. */+ inst_size += 1; /* mod r/m byte. */+ if (b & SLJIT_MEM) {+ if ((b & REG_MASK) == SLJIT_UNUSED)+ inst_size += sizeof(sljit_sw);+ else if (immb != 0 && !(b & OFFS_REG_MASK)) {+ /* Immediate operand. */+ if (immb <= 127 && immb >= -128)+ inst_size += sizeof(sljit_s8);+ else+ inst_size += sizeof(sljit_sw);+ }++ if ((b & REG_MASK) == SLJIT_SP && !(b & OFFS_REG_MASK))+ b |= TO_OFFS_REG(SLJIT_SP);++ if ((b & OFFS_REG_MASK) != SLJIT_UNUSED)+ inst_size += 1; /* SIB byte. */+ }++ /* Calculate size of a. */+ if (a & SLJIT_IMM) {+ if (flags & EX86_BIN_INS) {+ if (imma <= 127 && imma >= -128) {+ inst_size += 1;+ flags |= EX86_BYTE_ARG;+ } else+ inst_size += 4;+ }+ else if (flags & EX86_SHIFT_INS) {+ imma &= 0x1f;+ if (imma != 1) {+ inst_size ++;+ flags |= EX86_BYTE_ARG;+ }+ } else if (flags & EX86_BYTE_ARG)+ inst_size++;+ else if (flags & EX86_HALF_ARG)+ inst_size += sizeof(short);+ else+ inst_size += sizeof(sljit_sw);+ }+ else+ SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);+ PTR_FAIL_IF(!inst);++ /* Encoding the byte. */+ INC_SIZE(inst_size);+ if (flags & EX86_PREF_F2)+ *inst++ = 0xf2;+ if (flags & EX86_PREF_F3)+ *inst++ = 0xf3;+ if (flags & EX86_PREF_66)+ *inst++ = 0x66;++ buf_ptr = inst + size;++ /* Encode mod/rm byte. */+ if (!(flags & EX86_SHIFT_INS)) {+ if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))+ *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;++ if (a & SLJIT_IMM)+ *buf_ptr = 0;+ else if (!(flags & EX86_SSE2_OP1))+ *buf_ptr = reg_map[a] << 3;+ else+ *buf_ptr = a << 3;+ }+ else {+ if (a & SLJIT_IMM) {+ if (imma == 1)+ *inst = GROUP_SHIFT_1;+ else+ *inst = GROUP_SHIFT_N;+ } else+ *inst = GROUP_SHIFT_CL;+ *buf_ptr = 0;+ }++ if (!(b & SLJIT_MEM))+ *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_map[b] : b);+ else if ((b & REG_MASK) != SLJIT_UNUSED) {+ if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {+ if (immb != 0) {+ if (immb <= 127 && immb >= -128)+ *buf_ptr |= 0x40;+ else+ *buf_ptr |= 0x80;+ }++ if ((b & OFFS_REG_MASK) == SLJIT_UNUSED)+ *buf_ptr++ |= reg_map[b & REG_MASK];+ else {+ *buf_ptr++ |= 0x04;+ *buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3);+ }++ if (immb != 0) {+ if (immb <= 127 && immb >= -128)+ *buf_ptr++ = immb; /* 8 bit displacement. */+ else {+ sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */+ buf_ptr += sizeof(sljit_sw);+ }+ }+ }+ else {+ *buf_ptr++ |= 0x04;+ *buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3) | (immb << 6);+ }+ }+ else {+ *buf_ptr++ |= 0x05;+ sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */+ buf_ptr += sizeof(sljit_sw);+ }++ if (a & SLJIT_IMM) {+ if (flags & EX86_BYTE_ARG)+ *buf_ptr = imma;+ else if (flags & EX86_HALF_ARG)+ sljit_unaligned_store_s16(buf_ptr, imma);+ else if (!(flags & EX86_SHIFT_INS))+ sljit_unaligned_store_sw(buf_ptr, imma);+ }++ return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);+}++/* --------------------------------------------------------------------- */+/* Call / return instructions */+/* --------------------------------------------------------------------- */++#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)++static sljit_s32 c_fast_call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)+{+ sljit_s32 stack_size = 0;+ sljit_s32 word_arg_count = 0;++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ stack_size += sizeof(sljit_f32);+ break;+ case SLJIT_ARG_TYPE_F64:+ stack_size += sizeof(sljit_f64);+ break;+ default:+ word_arg_count++;+ if (word_arg_count > 2)+ stack_size += sizeof(sljit_sw);+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ if (word_arg_count_ptr)+ *word_arg_count_ptr = word_arg_count;++ return stack_size;+}++static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler,+ sljit_s32 arg_types, sljit_s32 stack_size, sljit_s32 word_arg_count, sljit_s32 swap_args)+{+ sljit_u8 *inst;+ sljit_s32 float_arg_count;++ if (stack_size == sizeof(sljit_sw) && word_arg_count == 3) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ PUSH_REG(reg_map[SLJIT_R2]);+ }+ else if (stack_size > 0) {+ if (word_arg_count >= 4)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->saveds_offset - sizeof(sljit_sw));++ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size));++ stack_size = 0;+ arg_types >>= SLJIT_DEF_SHIFT;+ word_arg_count = 0;+ float_arg_count = 0;+ while (arg_types) {+ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ float_arg_count++;+ FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));+ stack_size += sizeof(sljit_f32);+ break;+ case SLJIT_ARG_TYPE_F64:+ float_arg_count++;+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));+ stack_size += sizeof(sljit_f64);+ break;+ default:+ word_arg_count++;+ if (word_arg_count == 3) {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, SLJIT_R2, 0);+ stack_size += sizeof(sljit_sw);+ }+ else if (word_arg_count == 4) {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, TMP_REG1, 0);+ stack_size += sizeof(sljit_sw);+ }+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }+ }++ if (word_arg_count > 0) {+ if (swap_args) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);++ *inst++ = XCHG_EAX_r | reg_map[SLJIT_R2];+ }+ else {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);++ *inst++ = MOV_r_rm;+ *inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0];+ }+ }++ return SLJIT_SUCCESS;+}++#endif++static sljit_s32 cdecl_call_get_stack_size(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)+{+ sljit_s32 stack_size = 0;+ sljit_s32 word_arg_count = 0;++ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ stack_size += sizeof(sljit_f32);+ break;+ case SLJIT_ARG_TYPE_F64:+ stack_size += sizeof(sljit_f64);+ break;+ default:+ word_arg_count++;+ stack_size += sizeof(sljit_sw);+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ if (word_arg_count_ptr)+ *word_arg_count_ptr = word_arg_count;++ if (stack_size <= compiler->stack_tmp_size)+ return 0;++#if defined(__APPLE__)+ return ((stack_size - compiler->stack_tmp_size + 15) & ~15);+#else+ return stack_size - compiler->stack_tmp_size;+#endif+}++static sljit_s32 cdecl_call_with_args(struct sljit_compiler *compiler,+ sljit_s32 arg_types, sljit_s32 stack_size, sljit_s32 word_arg_count)+{+ sljit_s32 float_arg_count = 0;++ if (word_arg_count >= 4)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->saveds_offset - sizeof(sljit_sw));++ if (stack_size > 0)+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size));++ stack_size = 0;+ word_arg_count = 0;+ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ float_arg_count++;+ FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));+ stack_size += sizeof(sljit_f32);+ break;+ case SLJIT_ARG_TYPE_F64:+ float_arg_count++;+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));+ stack_size += sizeof(sljit_f64);+ break;+ default:+ word_arg_count++;+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, (word_arg_count >= 4) ? TMP_REG1 : word_arg_count, 0);+ stack_size += sizeof(sljit_sw);+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 post_call_with_args(struct sljit_compiler *compiler,+ sljit_s32 arg_types, sljit_s32 stack_size)+{+ sljit_u8 *inst;+ sljit_s32 single;++ if (stack_size > 0)+ FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size));++ if ((arg_types & SLJIT_DEF_MASK) < SLJIT_ARG_TYPE_F32)+ return SLJIT_SUCCESS;++ single = ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);+ FAIL_IF(!inst);+ INC_SIZE(3);+ inst[0] = single ? FSTPS : FSTPD;+ inst[1] = (0x03 << 3) | 0x04;+ inst[2] = (0x04 << 3) | reg_map[SLJIT_SP];++ return emit_sse2_load(compiler, single, SLJIT_FR0, SLJIT_MEM1(SLJIT_SP), 0);+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ struct sljit_jump *jump;+ sljit_s32 stack_size = 0;+ sljit_s32 word_arg_count;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ if ((type & 0xff) == SLJIT_CALL) {+ stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count);+ PTR_FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, 0));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ jump = sljit_emit_jump(compiler, type);+ PTR_FAIL_IF(jump == NULL);++ PTR_FAIL_IF(post_call_with_args(compiler, arg_types, 0));+ return jump;+ }+#endif++ stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count);+ PTR_FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ jump = sljit_emit_jump(compiler, type);+ PTR_FAIL_IF(jump == NULL);++ PTR_FAIL_IF(post_call_with_args(compiler, arg_types, stack_size));+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 stack_size = 0;+ sljit_s32 word_arg_count;+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ sljit_s32 swap_args;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ SLJIT_ASSERT(reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R2] == 1 && SLJIT_R0 == 1 && SLJIT_R2 == 3);++ if ((type & 0xff) == SLJIT_CALL) {+ stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count);+ swap_args = 0;++ if (word_arg_count > 0) {+ if ((src & REG_MASK) == SLJIT_R2 || OFFS_REG(src) == SLJIT_R2) {+ swap_args = 1;+ if (((src & REG_MASK) | 0x2) == SLJIT_R2)+ src ^= 0x2;+ if ((OFFS_REG(src) | 0x2) == SLJIT_R2)+ src ^= TO_OFFS_REG(0x2);+ }+ }++ FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, swap_args));++ compiler->saveds_offset += stack_size;+ compiler->locals_offset += stack_size;++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));++ compiler->saveds_offset -= stack_size;+ compiler->locals_offset -= stack_size;++ return post_call_with_args(compiler, arg_types, 0);+ }+#endif++ stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count);+ FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count));++ compiler->saveds_offset += stack_size;+ compiler->locals_offset += stack_size;++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));++ compiler->saveds_offset -= stack_size;+ compiler->locals_offset -= stack_size;++ return post_call_with_args(compiler, arg_types, stack_size);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ sljit_u8 *inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);++ /* For UNUSED dst. Uncommon, but possible. */+ if (dst == SLJIT_UNUSED)+ dst = TMP_REG1;++ if (FAST_IS_REG(dst)) {+ /* Unused dest is possible here. */+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);++ INC_SIZE(1);+ POP_REG(reg_map[dst]);+ return SLJIT_SUCCESS;+ }++ /* Memory. */+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst++ = POP_rm;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)+{+ sljit_u8 *inst;++ CHECK_EXTRA_REGS(src, srcw, (void)0);++ if (FAST_IS_REG(src)) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);+ FAIL_IF(!inst);++ INC_SIZE(1 + 1);+ PUSH_REG(reg_map[src]);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = GROUP_FF;+ *inst |= PUSH_rm;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ }++ RET();+ return SLJIT_SUCCESS;+}++static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)+{+ sljit_s32 size, saved_size;+ sljit_s32 has_f64_aligment;++ /* Don't adjust shadow stack if it isn't enabled. */+ if (!cpu_has_shadow_stack ())+ return SLJIT_SUCCESS;++ SLJIT_ASSERT(compiler->args >= 0);+ SLJIT_ASSERT(compiler->local_size > 0);++#if !defined(__APPLE__)+ has_f64_aligment = compiler->options & SLJIT_F64_ALIGNMENT;+#else+ has_f64_aligment = 0;+#endif++ size = compiler->local_size;+ saved_size = (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) + (compiler->saveds <= 3 ? compiler->saveds : 3)) * sizeof(sljit_uw);+ if (has_f64_aligment) {+ /* mov TMP_REG1, [esp + local_size]. */+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), size);+ /* mov TMP_REG1, [TMP_REG1+ saved_size]. */+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), saved_size);+ /* Move return address to [esp]. */+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, TMP_REG1, 0);+ size = 0;+ } else+ size += saved_size;++ return adjust_shadow_stack(compiler, SLJIT_UNUSED, 0, SLJIT_SP, size);+}
+ src/c/pcre2/src/sljit/sljitNativeX86_64.c view
@@ -0,0 +1,918 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/* x86 64-bit arch dependent functions. */++static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)+{+ sljit_u8 *inst;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));+ FAIL_IF(!inst);+ INC_SIZE(2 + sizeof(sljit_sw));+ *inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);+ *inst++ = MOV_r_i32 + (reg_map[reg] & 0x7);+ sljit_unaligned_store_sw(inst, imm);+ return SLJIT_SUCCESS;+}++static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr)+{+ sljit_s32 type = jump->flags >> TYPE_SHIFT;++ int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff);++ /* The relative jump below specialized for this case. */+ SLJIT_ASSERT(reg_map[TMP_REG2] >= 8);++ if (type < SLJIT_JUMP) {+ /* Invert type. */+ *code_ptr++ = get_jump_code(type ^ 0x1) - 0x10;+ *code_ptr++ = short_addr ? (6 + 3) : (10 + 3);+ }++ *code_ptr++ = short_addr ? REX_B : (REX_W | REX_B);+ *code_ptr++ = MOV_r_i32 | reg_lmap[TMP_REG2];+ jump->addr = (sljit_uw)code_ptr;++ if (jump->flags & JUMP_LABEL)+ jump->flags |= PATCH_MD;+ else if (short_addr)+ sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target);+ else+ sljit_unaligned_store_sw(code_ptr, jump->u.target);++ code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw);++ *code_ptr++ = REX_B;+ *code_ptr++ = GROUP_FF;+ *code_ptr++ = MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2];++ return code_ptr;+}++static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label)+{+ if (max_label > HALFWORD_MAX) {+ put_label->addr -= put_label->flags;+ put_label->flags = PATCH_MD;+ return code_ptr;+ }++ if (put_label->flags == 0) {+ /* Destination is register. */+ code_ptr = (sljit_u8*)put_label->addr - 2 - sizeof(sljit_uw);++ SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);+ SLJIT_ASSERT((code_ptr[1] & 0xf8) == MOV_r_i32);++ if ((code_ptr[0] & 0x07) != 0) {+ code_ptr[0] = (sljit_u8)(code_ptr[0] & ~0x08);+ code_ptr += 2 + sizeof(sljit_s32);+ }+ else {+ code_ptr[0] = code_ptr[1];+ code_ptr += 1 + sizeof(sljit_s32);+ }++ put_label->addr = (sljit_uw)code_ptr;+ return code_ptr;+ }++ code_ptr -= put_label->flags + (2 + sizeof(sljit_uw));+ SLJIT_MEMMOVE(code_ptr, code_ptr + (2 + sizeof(sljit_uw)), put_label->flags);++ SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);++ if ((code_ptr[1] & 0xf8) == MOV_r_i32) {+ code_ptr += 2 + sizeof(sljit_uw);+ SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);+ }++ SLJIT_ASSERT(code_ptr[1] == MOV_rm_r);++ code_ptr[0] = (sljit_u8)(code_ptr[0] & ~0x4);+ code_ptr[1] = MOV_rm_i32;+ code_ptr[2] = (sljit_u8)(code_ptr[2] & ~(0x7 << 3));++ code_ptr = (sljit_u8*)(put_label->addr - (2 + sizeof(sljit_uw)) + sizeof(sljit_s32));+ put_label->addr = (sljit_uw)code_ptr;+ put_label->flags = 0;+ return code_ptr;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 args, i, tmp, size, saved_register_size;+ sljit_u8 *inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++ /* Emit ENDBR64 at function entry if needed. */+ FAIL_IF(emit_endbranch(compiler));++ compiler->mode32 = 0;++#ifdef _WIN64+ /* Two/four register slots for parameters plus space for xmm6 register if needed. */+ if (fscratches >= 6 || fsaveds >= 1)+ compiler->locals_offset = 6 * sizeof(sljit_sw);+ else+ compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw);+#endif++ /* Including the return address saved by the call instruction. */+ saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);++ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = SLJIT_S0; i >= tmp; i--) {+ size = reg_map[i] >= 8 ? 2 : 1;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ if (reg_map[i] >= 8)+ *inst++ = REX_B;+ PUSH_REG(reg_lmap[i]);+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ size = reg_map[i] >= 8 ? 2 : 1;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ if (reg_map[i] >= 8)+ *inst++ = REX_B;+ PUSH_REG(reg_lmap[i]);+ }++ args = get_arg_count(arg_types);++ if (args > 0) {+ size = args * 3;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);++ INC_SIZE(size);++#ifndef _WIN64+ if (args > 0) {+ inst[0] = REX_W;+ inst[1] = MOV_r_rm;+ inst[2] = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x7 /* rdi */;+ inst += 3;+ }+ if (args > 1) {+ inst[0] = REX_W | REX_R;+ inst[1] = MOV_r_rm;+ inst[2] = MOD_REG | (reg_lmap[SLJIT_S1] << 3) | 0x6 /* rsi */;+ inst += 3;+ }+ if (args > 2) {+ inst[0] = REX_W | REX_R;+ inst[1] = MOV_r_rm;+ inst[2] = MOD_REG | (reg_lmap[SLJIT_S2] << 3) | 0x2 /* rdx */;+ }+#else+ if (args > 0) {+ inst[0] = REX_W;+ inst[1] = MOV_r_rm;+ inst[2] = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x1 /* rcx */;+ inst += 3;+ }+ if (args > 1) {+ inst[0] = REX_W;+ inst[1] = MOV_r_rm;+ inst[2] = MOD_REG | (reg_map[SLJIT_S1] << 3) | 0x2 /* rdx */;+ inst += 3;+ }+ if (args > 2) {+ inst[0] = REX_W | REX_B;+ inst[1] = MOV_r_rm;+ inst[2] = MOD_REG | (reg_map[SLJIT_S2] << 3) | 0x0 /* r8 */;+ }+#endif+ }++ local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size;+ compiler->local_size = local_size;++#ifdef _WIN64+ if (local_size > 0) {+ if (local_size <= 4 * 4096) {+ if (local_size > 4096)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096);+ if (local_size > 2 * 4096)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);+ if (local_size > 3 * 4096)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);+ }+ else {+ EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_SP, 0);+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, (local_size - 1) >> 12);++ SLJIT_ASSERT (reg_map[SLJIT_R0] == 0);++ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_MEM1(SLJIT_R0), -4096);+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4096));+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, 1));++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);++ INC_SIZE(2);+ inst[0] = JNE_i8;+ inst[1] = (sljit_s8) -19;+ }++ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size);+ }+#endif++ if (local_size > 0) {+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));+ }++#ifdef _WIN64+ /* Save xmm6 register: movaps [rsp + 0x20], xmm6 */+ if (fscratches >= 6 || fsaveds >= 1) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);+ FAIL_IF(!inst);+ INC_SIZE(5);+ *inst++ = GROUP_0F;+ sljit_unaligned_store_s32(inst, 0x20247429);+ }+#endif++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)+{+ sljit_s32 saved_register_size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);++#ifdef _WIN64+ /* Two/four register slots for parameters plus space for xmm6 register if needed. */+ if (fscratches >= 6 || fsaveds >= 1)+ compiler->locals_offset = 6 * sizeof(sljit_sw);+ else+ compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw);+#endif++ /* Including the return address saved by the call instruction. */+ saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);+ compiler->local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size;+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 i, tmp, size;+ sljit_u8 *inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));++ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));++#ifdef _WIN64+ /* Restore xmm6 register: movaps xmm6, [rsp + 0x20] */+ if (compiler->fscratches >= 6 || compiler->fsaveds >= 1) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);+ FAIL_IF(!inst);+ INC_SIZE(5);+ *inst++ = GROUP_0F;+ sljit_unaligned_store_s32(inst, 0x20247428);+ }+#endif++ if (compiler->local_size > 0) {+ if (compiler->local_size <= 127) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ *inst++ = REX_W;+ *inst++ = GROUP_BINARY_83;+ *inst++ = MOD_REG | ADD | 4;+ *inst = compiler->local_size;+ }+ else {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);+ FAIL_IF(!inst);+ INC_SIZE(7);+ *inst++ = REX_W;+ *inst++ = GROUP_BINARY_81;+ *inst++ = MOD_REG | ADD | 4;+ sljit_unaligned_store_s32(inst, compiler->local_size);+ }+ }++ tmp = compiler->scratches;+ for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {+ size = reg_map[i] >= 8 ? 2 : 1;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ if (reg_map[i] >= 8)+ *inst++ = REX_B;+ POP_REG(reg_lmap[i]);+ }++ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;+ for (i = tmp; i <= SLJIT_S0; i++) {+ size = reg_map[i] >= 8 ? 2 : 1;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ if (reg_map[i] >= 8)+ *inst++ = REX_B;+ POP_REG(reg_lmap[i]);+ }++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ RET();+ return SLJIT_SUCCESS;+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++static sljit_s32 emit_do_imm32(struct sljit_compiler *compiler, sljit_u8 rex, sljit_u8 opcode, sljit_sw imm)+{+ sljit_u8 *inst;+ sljit_s32 length = 1 + (rex ? 1 : 0) + sizeof(sljit_s32);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + length);+ FAIL_IF(!inst);+ INC_SIZE(length);+ if (rex)+ *inst++ = rex;+ *inst++ = opcode;+ sljit_unaligned_store_s32(inst, imm);+ return SLJIT_SUCCESS;+}++static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size,+ /* The register or immediate operand. */+ sljit_s32 a, sljit_sw imma,+ /* The general operand (not immediate). */+ sljit_s32 b, sljit_sw immb)+{+ sljit_u8 *inst;+ sljit_u8 *buf_ptr;+ sljit_u8 rex = 0;+ sljit_s32 flags = size & ~0xf;+ sljit_s32 inst_size;++ /* The immediate operand must be 32 bit. */+ SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));+ /* Both cannot be switched on. */+ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));+ /* Size flags not allowed for typed instructions. */+ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);+ /* Both size flags cannot be switched on. */+ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));+ /* SSE2 and immediate is not possible. */+ SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));+ SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)+ && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)+ && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));++ size &= 0xf;+ inst_size = size;++ if (!compiler->mode32 && !(flags & EX86_NO_REXW))+ rex |= REX_W;+ else if (flags & EX86_REX)+ rex |= REX;++ if (flags & (EX86_PREF_F2 | EX86_PREF_F3))+ inst_size++;+ if (flags & EX86_PREF_66)+ inst_size++;++ /* Calculate size of b. */+ inst_size += 1; /* mod r/m byte. */+ if (b & SLJIT_MEM) {+ if (!(b & OFFS_REG_MASK)) {+ if (NOT_HALFWORD(immb)) {+ PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));+ immb = 0;+ if (b & REG_MASK)+ b |= TO_OFFS_REG(TMP_REG2);+ else+ b |= TMP_REG2;+ }+ else if (reg_lmap[b & REG_MASK] == 4)+ b |= TO_OFFS_REG(SLJIT_SP);+ }++ if ((b & REG_MASK) == SLJIT_UNUSED)+ inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */+ else {+ if (reg_map[b & REG_MASK] >= 8)+ rex |= REX_B;++ if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) {+ /* Immediate operand. */+ if (immb <= 127 && immb >= -128)+ inst_size += sizeof(sljit_s8);+ else+ inst_size += sizeof(sljit_s32);+ }+ else if (reg_lmap[b & REG_MASK] == 5)+ inst_size += sizeof(sljit_s8);++ if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) {+ inst_size += 1; /* SIB byte. */+ if (reg_map[OFFS_REG(b)] >= 8)+ rex |= REX_X;+ }+ }+ }+ else if (!(flags & EX86_SSE2_OP2)) {+ if (reg_map[b] >= 8)+ rex |= REX_B;+ }+ else if (freg_map[b] >= 8)+ rex |= REX_B;++ if (a & SLJIT_IMM) {+ if (flags & EX86_BIN_INS) {+ if (imma <= 127 && imma >= -128) {+ inst_size += 1;+ flags |= EX86_BYTE_ARG;+ } else+ inst_size += 4;+ }+ else if (flags & EX86_SHIFT_INS) {+ imma &= compiler->mode32 ? 0x1f : 0x3f;+ if (imma != 1) {+ inst_size ++;+ flags |= EX86_BYTE_ARG;+ }+ } else if (flags & EX86_BYTE_ARG)+ inst_size++;+ else if (flags & EX86_HALF_ARG)+ inst_size += sizeof(short);+ else+ inst_size += sizeof(sljit_s32);+ }+ else {+ SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);+ /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */+ if (!(flags & EX86_SSE2_OP1)) {+ if (reg_map[a] >= 8)+ rex |= REX_R;+ }+ else if (freg_map[a] >= 8)+ rex |= REX_R;+ }++ if (rex)+ inst_size++;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);+ PTR_FAIL_IF(!inst);++ /* Encoding the byte. */+ INC_SIZE(inst_size);+ if (flags & EX86_PREF_F2)+ *inst++ = 0xf2;+ if (flags & EX86_PREF_F3)+ *inst++ = 0xf3;+ if (flags & EX86_PREF_66)+ *inst++ = 0x66;+ if (rex)+ *inst++ = rex;+ buf_ptr = inst + size;++ /* Encode mod/rm byte. */+ if (!(flags & EX86_SHIFT_INS)) {+ if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))+ *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;++ if (a & SLJIT_IMM)+ *buf_ptr = 0;+ else if (!(flags & EX86_SSE2_OP1))+ *buf_ptr = reg_lmap[a] << 3;+ else+ *buf_ptr = freg_lmap[a] << 3;+ }+ else {+ if (a & SLJIT_IMM) {+ if (imma == 1)+ *inst = GROUP_SHIFT_1;+ else+ *inst = GROUP_SHIFT_N;+ } else+ *inst = GROUP_SHIFT_CL;+ *buf_ptr = 0;+ }++ if (!(b & SLJIT_MEM))+ *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : freg_lmap[b]);+ else if ((b & REG_MASK) != SLJIT_UNUSED) {+ if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {+ if (immb != 0 || reg_lmap[b & REG_MASK] == 5) {+ if (immb <= 127 && immb >= -128)+ *buf_ptr |= 0x40;+ else+ *buf_ptr |= 0x80;+ }++ if ((b & OFFS_REG_MASK) == SLJIT_UNUSED)+ *buf_ptr++ |= reg_lmap[b & REG_MASK];+ else {+ *buf_ptr++ |= 0x04;+ *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3);+ }++ if (immb != 0 || reg_lmap[b & REG_MASK] == 5) {+ if (immb <= 127 && immb >= -128)+ *buf_ptr++ = immb; /* 8 bit displacement. */+ else {+ sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */+ buf_ptr += sizeof(sljit_s32);+ }+ }+ }+ else {+ if (reg_lmap[b & REG_MASK] == 5)+ *buf_ptr |= 0x40;+ *buf_ptr++ |= 0x04;+ *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6);+ if (reg_lmap[b & REG_MASK] == 5)+ *buf_ptr++ = 0;+ }+ }+ else {+ *buf_ptr++ |= 0x04;+ *buf_ptr++ = 0x25;+ sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */+ buf_ptr += sizeof(sljit_s32);+ }++ if (a & SLJIT_IMM) {+ if (flags & EX86_BYTE_ARG)+ *buf_ptr = imma;+ else if (flags & EX86_HALF_ARG)+ sljit_unaligned_store_s16(buf_ptr, imma);+ else if (!(flags & EX86_SHIFT_INS))+ sljit_unaligned_store_s32(buf_ptr, imma);+ }++ return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);+}++/* --------------------------------------------------------------------- */+/* Call / return instructions */+/* --------------------------------------------------------------------- */++#ifndef _WIN64++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr, sljit_sw srcw)+{+ sljit_s32 src = src_ptr ? (*src_ptr) : 0;+ sljit_s32 word_arg_count = 0;++ SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R3] == 1 && reg_map[TMP_REG1] == 2);++ compiler->mode32 = 0;++ /* Remove return value. */+ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ if ((arg_types & SLJIT_DEF_MASK) < SLJIT_ARG_TYPE_F32)+ word_arg_count++;+ arg_types >>= SLJIT_DEF_SHIFT;+ }++ if (word_arg_count == 0)+ return SLJIT_SUCCESS;++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);+ *src_ptr = TMP_REG2;+ }+ else if (src == SLJIT_R2 && word_arg_count >= SLJIT_R2)+ *src_ptr = TMP_REG1;++ if (word_arg_count >= 3)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R2, 0);+ return emit_mov(compiler, SLJIT_R2, 0, SLJIT_R0, 0);+}++#else++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr, sljit_sw srcw)+{+ sljit_s32 src = src_ptr ? (*src_ptr) : 0;+ sljit_s32 arg_count = 0;+ sljit_s32 word_arg_count = 0;+ sljit_s32 float_arg_count = 0;+ sljit_s32 types = 0;+ sljit_s32 data_trandfer = 0;+ static sljit_u8 word_arg_regs[5] = { 0, SLJIT_R3, SLJIT_R1, SLJIT_R2, TMP_REG1 };++ SLJIT_ASSERT(reg_map[SLJIT_R3] == 1 && reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R2] == 8 && reg_map[TMP_REG1] == 9);++ compiler->mode32 = 0;+ arg_types >>= SLJIT_DEF_SHIFT;++ while (arg_types) {+ types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);++ switch (arg_types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ case SLJIT_ARG_TYPE_F64:+ arg_count++;+ float_arg_count++;++ if (arg_count != float_arg_count)+ data_trandfer = 1;+ break;+ default:+ arg_count++;+ word_arg_count++;++ if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count]) {+ data_trandfer = 1;++ if (src == word_arg_regs[arg_count]) {+ EMIT_MOV(compiler, TMP_REG2, 0, src, 0);+ *src_ptr = TMP_REG2;+ }+ }+ break;+ }++ arg_types >>= SLJIT_DEF_SHIFT;+ }++ if (!data_trandfer)+ return SLJIT_SUCCESS;++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);+ *src_ptr = TMP_REG2;+ }++ while (types) {+ switch (types & SLJIT_DEF_MASK) {+ case SLJIT_ARG_TYPE_F32:+ if (arg_count != float_arg_count)+ FAIL_IF(emit_sse2_load(compiler, 1, arg_count, float_arg_count, 0));+ arg_count--;+ float_arg_count--;+ break;+ case SLJIT_ARG_TYPE_F64:+ if (arg_count != float_arg_count)+ FAIL_IF(emit_sse2_load(compiler, 0, arg_count, float_arg_count, 0));+ arg_count--;+ float_arg_count--;+ break;+ default:+ if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count])+ EMIT_MOV(compiler, word_arg_regs[arg_count], 0, word_arg_count, 0);+ arg_count--;+ word_arg_count--;+ break;+ }++ types >>= SLJIT_DEF_SHIFT;+ }++ return SLJIT_SUCCESS;+}++#endif++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types)+{+ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL, 0));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_jump(compiler, type);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 arg_types,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));++ FAIL_IF(call_with_args(compiler, arg_types, &src, srcw));++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif++ return sljit_emit_ijump(compiler, type, src, srcw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ sljit_u8 *inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ /* For UNUSED dst. Uncommon, but possible. */+ if (dst == SLJIT_UNUSED)+ dst = TMP_REG1;++ if (FAST_IS_REG(dst)) {+ if (reg_map[dst] < 8) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ POP_REG(reg_lmap[dst]);+ return SLJIT_SUCCESS;+ }++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ *inst++ = REX_B;+ POP_REG(reg_lmap[dst]);+ return SLJIT_SUCCESS;+ }++ /* REX_W is not necessary (src is not immediate). */+ compiler->mode32 = 1;+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst++ = POP_rm;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)+{+ sljit_u8 *inst;++ if (FAST_IS_REG(src)) {+ if (reg_map[src] < 8) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);+ FAIL_IF(!inst);++ INC_SIZE(1 + 1);+ PUSH_REG(reg_lmap[src]);+ }+ else {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 1);+ FAIL_IF(!inst);++ INC_SIZE(2 + 1);+ *inst++ = REX_B;+ PUSH_REG(reg_lmap[src]);+ }+ }+ else {+ /* REX_W is not necessary (src is not immediate). */+ compiler->mode32 = 1;+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = GROUP_FF;+ *inst |= PUSH_rm;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ }++ RET();+ return SLJIT_SUCCESS;+}++/* --------------------------------------------------------------------- */+/* Extend input */+/* --------------------------------------------------------------------- */++static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;+ sljit_s32 dst_r;++ compiler->mode32 = 0;++ if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))+ return SLJIT_SUCCESS; /* Empty instruction. */++ if (src & SLJIT_IMM) {+ if (FAST_IS_REG(dst)) {+ if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ return SLJIT_SUCCESS;+ }+ return emit_load_imm64(compiler, dst, srcw);+ }+ compiler->mode32 = 1;+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ compiler->mode32 = 0;+ return SLJIT_SUCCESS;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if ((dst & SLJIT_MEM) && FAST_IS_REG(src))+ dst_r = src;+ else {+ if (sign) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = MOVSXD_r_rm;+ } else {+ compiler->mode32 = 1;+ FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));+ compiler->mode32 = 0;+ }+ }++ if (dst & SLJIT_MEM) {+ compiler->mode32 = 1;+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_r;+ compiler->mode32 = 0;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)+{+ sljit_s32 tmp, size;++ /* Don't adjust shadow stack if it isn't enabled. */+ if (!cpu_has_shadow_stack ())+ return SLJIT_SUCCESS;++ size = compiler->local_size;+ tmp = compiler->scratches;+ if (tmp >= SLJIT_FIRST_SAVED_REG)+ size += (tmp - SLJIT_FIRST_SAVED_REG + 1) * sizeof(sljit_uw);+ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;+ if (SLJIT_S0 >= tmp)+ size += (SLJIT_S0 - tmp + 1) * sizeof(sljit_uw);++ return adjust_shadow_stack(compiler, SLJIT_UNUSED, 0, SLJIT_SP, size);+}
+ src/c/pcre2/src/sljit/sljitNativeX86_common.c view
@@ -0,0 +1,3142 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)+ return "x86" SLJIT_CPUINFO " ABI:fastcall";+#else+ return "x86" SLJIT_CPUINFO;+#endif+}++/*+ 32b register indexes:+ 0 - EAX+ 1 - ECX+ 2 - EDX+ 3 - EBX+ 4 - ESP+ 5 - EBP+ 6 - ESI+ 7 - EDI+*/++/*+ 64b register indexes:+ 0 - RAX+ 1 - RCX+ 2 - RDX+ 3 - RBX+ 4 - RSP+ 5 - RBP+ 6 - RSI+ 7 - RDI+ 8 - R8 - From now on REX prefix is required+ 9 - R9+ 10 - R10+ 11 - R11+ 12 - R12+ 13 - R13+ 14 - R14+ 15 - R15+*/++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)++/* Last register + 1. */+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)++static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {+ 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 7, 6, 3, 4, 5+};++#define CHECK_EXTRA_REGS(p, w, do) \+ if (p >= SLJIT_R3 && p <= SLJIT_S3) { \+ if (p <= compiler->scratches) \+ w = compiler->saveds_offset - ((p) - SLJIT_R2) * (sljit_sw)sizeof(sljit_sw); \+ else \+ w = compiler->locals_offset + ((p) - SLJIT_S2) * (sljit_sw)sizeof(sljit_sw); \+ p = SLJIT_MEM1(SLJIT_SP); \+ do; \+ }++#else /* SLJIT_CONFIG_X86_32 */++/* Last register + 1. */+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)++/* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present+ Note: avoid to use r12 and r13 for memory addessing+ therefore r12 is better to be a higher saved register. */+#ifndef _WIN64+/* Args: rdi(=7), rsi(=6), rdx(=2), rcx(=1), r8, r9. Scratches: rax(=0), r10, r11 */+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {+ 0, 0, 6, 7, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9+};+/* low-map. reg_map & 0x7. */+static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {+ 0, 0, 6, 7, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1+};+#else+/* Args: rcx(=1), rdx(=2), r8, r9. Scratches: rax(=0), r10, r11 */+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {+ 0, 0, 2, 8, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 9, 10+};+/* low-map. reg_map & 0x7. */+static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {+ 0, 0, 2, 0, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 1, 2+};+#endif++/* Args: xmm0-xmm3 */+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {+ 4, 0, 1, 2, 3, 5, 6+};+/* low-map. freg_map & 0x7. */+static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {+ 4, 0, 1, 2, 3, 5, 6+};++#define REX_W 0x48+#define REX_R 0x44+#define REX_X 0x42+#define REX_B 0x41+#define REX 0x40++#ifndef _WIN64+#define HALFWORD_MAX 0x7fffffffl+#define HALFWORD_MIN -0x80000000l+#else+#define HALFWORD_MAX 0x7fffffffll+#define HALFWORD_MIN -0x80000000ll+#endif++#define IS_HALFWORD(x) ((x) <= HALFWORD_MAX && (x) >= HALFWORD_MIN)+#define NOT_HALFWORD(x) ((x) > HALFWORD_MAX || (x) < HALFWORD_MIN)++#define CHECK_EXTRA_REGS(p, w, do)++#endif /* SLJIT_CONFIG_X86_32 */++#define TMP_FREG (0)++/* Size flags for emit_x86_instruction: */+#define EX86_BIN_INS 0x0010+#define EX86_SHIFT_INS 0x0020+#define EX86_REX 0x0040+#define EX86_NO_REXW 0x0080+#define EX86_BYTE_ARG 0x0100+#define EX86_HALF_ARG 0x0200+#define EX86_PREF_66 0x0400+#define EX86_PREF_F2 0x0800+#define EX86_PREF_F3 0x1000+#define EX86_SSE2_OP1 0x2000+#define EX86_SSE2_OP2 0x4000+#define EX86_SSE2 (EX86_SSE2_OP1 | EX86_SSE2_OP2)++/* --------------------------------------------------------------------- */+/* Instrucion forms */+/* --------------------------------------------------------------------- */++#define ADD (/* BINARY */ 0 << 3)+#define ADD_EAX_i32 0x05+#define ADD_r_rm 0x03+#define ADD_rm_r 0x01+#define ADDSD_x_xm 0x58+#define ADC (/* BINARY */ 2 << 3)+#define ADC_EAX_i32 0x15+#define ADC_r_rm 0x13+#define ADC_rm_r 0x11+#define AND (/* BINARY */ 4 << 3)+#define AND_EAX_i32 0x25+#define AND_r_rm 0x23+#define AND_rm_r 0x21+#define ANDPD_x_xm 0x54+#define BSR_r_rm (/* GROUP_0F */ 0xbd)+#define CALL_i32 0xe8+#define CALL_rm (/* GROUP_FF */ 2 << 3)+#define CDQ 0x99+#define CMOVE_r_rm (/* GROUP_0F */ 0x44)+#define CMP (/* BINARY */ 7 << 3)+#define CMP_EAX_i32 0x3d+#define CMP_r_rm 0x3b+#define CMP_rm_r 0x39+#define CVTPD2PS_x_xm 0x5a+#define CVTSI2SD_x_rm 0x2a+#define CVTTSD2SI_r_xm 0x2c+#define DIV (/* GROUP_F7 */ 6 << 3)+#define DIVSD_x_xm 0x5e+#define FSTPS 0xd9+#define FSTPD 0xdd+#define INT3 0xcc+#define IDIV (/* GROUP_F7 */ 7 << 3)+#define IMUL (/* GROUP_F7 */ 5 << 3)+#define IMUL_r_rm (/* GROUP_0F */ 0xaf)+#define IMUL_r_rm_i8 0x6b+#define IMUL_r_rm_i32 0x69+#define JE_i8 0x74+#define JNE_i8 0x75+#define JMP_i8 0xeb+#define JMP_i32 0xe9+#define JMP_rm (/* GROUP_FF */ 4 << 3)+#define LEA_r_m 0x8d+#define MOV_r_rm 0x8b+#define MOV_r_i32 0xb8+#define MOV_rm_r 0x89+#define MOV_rm_i32 0xc7+#define MOV_rm8_i8 0xc6+#define MOV_rm8_r8 0x88+#define MOVSD_x_xm 0x10+#define MOVSD_xm_x 0x11+#define MOVSXD_r_rm 0x63+#define MOVSX_r_rm8 (/* GROUP_0F */ 0xbe)+#define MOVSX_r_rm16 (/* GROUP_0F */ 0xbf)+#define MOVZX_r_rm8 (/* GROUP_0F */ 0xb6)+#define MOVZX_r_rm16 (/* GROUP_0F */ 0xb7)+#define MUL (/* GROUP_F7 */ 4 << 3)+#define MULSD_x_xm 0x59+#define NEG_rm (/* GROUP_F7 */ 3 << 3)+#define NOP 0x90+#define NOT_rm (/* GROUP_F7 */ 2 << 3)+#define OR (/* BINARY */ 1 << 3)+#define OR_r_rm 0x0b+#define OR_EAX_i32 0x0d+#define OR_rm_r 0x09+#define OR_rm8_r8 0x08+#define POP_r 0x58+#define POP_rm 0x8f+#define POPF 0x9d+#define PREFETCH 0x18+#define PUSH_i32 0x68+#define PUSH_r 0x50+#define PUSH_rm (/* GROUP_FF */ 6 << 3)+#define PUSHF 0x9c+#define RET_near 0xc3+#define RET_i16 0xc2+#define SBB (/* BINARY */ 3 << 3)+#define SBB_EAX_i32 0x1d+#define SBB_r_rm 0x1b+#define SBB_rm_r 0x19+#define SAR (/* SHIFT */ 7 << 3)+#define SHL (/* SHIFT */ 4 << 3)+#define SHR (/* SHIFT */ 5 << 3)+#define SUB (/* BINARY */ 5 << 3)+#define SUB_EAX_i32 0x2d+#define SUB_r_rm 0x2b+#define SUB_rm_r 0x29+#define SUBSD_x_xm 0x5c+#define TEST_EAX_i32 0xa9+#define TEST_rm_r 0x85+#define UCOMISD_x_xm 0x2e+#define UNPCKLPD_x_xm 0x14+#define XCHG_EAX_r 0x90+#define XCHG_r_rm 0x87+#define XOR (/* BINARY */ 6 << 3)+#define XOR_EAX_i32 0x35+#define XOR_r_rm 0x33+#define XOR_rm_r 0x31+#define XORPD_x_xm 0x57++#define GROUP_0F 0x0f+#define GROUP_F7 0xf7+#define GROUP_FF 0xff+#define GROUP_BINARY_81 0x81+#define GROUP_BINARY_83 0x83+#define GROUP_SHIFT_1 0xd1+#define GROUP_SHIFT_N 0xc1+#define GROUP_SHIFT_CL 0xd3++#define MOD_REG 0xc0+#define MOD_DISP8 0x40++#define INC_SIZE(s) (*inst++ = (s), compiler->size += (s))++#define PUSH_REG(r) (*inst++ = (PUSH_r + (r)))+#define POP_REG(r) (*inst++ = (POP_r + (r)))+#define RET() (*inst++ = (RET_near))+#define RET_I16(n) (*inst++ = (RET_i16), *inst++ = n, *inst++ = 0)+/* r32, r/m32 */+#define MOV_RM(mod, reg, rm) (*inst++ = (MOV_r_rm), *inst++ = (mod) << 6 | (reg) << 3 | (rm))++/* Multithreading does not affect these static variables, since they store+ built-in CPU features. Therefore they can be overwritten by different threads+ if they detect the CPU features in the same time. */+#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)+static sljit_s32 cpu_has_sse2 = -1;+#endif+static sljit_s32 cpu_has_cmov = -1;++#ifdef _WIN32_WCE+#include <cmnintrin.h>+#elif defined(_MSC_VER) && _MSC_VER >= 1400+#include <intrin.h>+#endif++/******************************************************/+/* Unaligned-store functions */+/******************************************************/++static SLJIT_INLINE void sljit_unaligned_store_s16(void *addr, sljit_s16 value)+{+ SLJIT_MEMCPY(addr, &value, sizeof(value));+}++static SLJIT_INLINE void sljit_unaligned_store_s32(void *addr, sljit_s32 value)+{+ SLJIT_MEMCPY(addr, &value, sizeof(value));+}++static SLJIT_INLINE void sljit_unaligned_store_sw(void *addr, sljit_sw value)+{+ SLJIT_MEMCPY(addr, &value, sizeof(value));+}++/******************************************************/+/* Utility functions */+/******************************************************/++static void get_cpu_features(void)+{+ sljit_u32 features;++#if defined(_MSC_VER) && _MSC_VER >= 1400++ int CPUInfo[4];+ __cpuid(CPUInfo, 1);+ features = (sljit_u32)CPUInfo[3];++#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C)++ /* AT&T syntax. */+ __asm__ (+ "movl $0x1, %%eax\n"+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ /* On x86-32, there is no red zone, so this+ should work (no need for a local variable). */+ "push %%ebx\n"+#endif+ "cpuid\n"+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ "pop %%ebx\n"+#endif+ "movl %%edx, %0\n"+ : "=g" (features)+ :+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ : "%eax", "%ecx", "%edx"+#else+ : "%rax", "%rbx", "%rcx", "%rdx"+#endif+ );++#else /* _MSC_VER && _MSC_VER >= 1400 */++ /* Intel syntax. */+ __asm {+ mov eax, 1+ cpuid+ mov features, edx+ }++#endif /* _MSC_VER && _MSC_VER >= 1400 */++#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)+ cpu_has_sse2 = (features >> 26) & 0x1;+#endif+ cpu_has_cmov = (features >> 15) & 0x1;+}++static sljit_u8 get_jump_code(sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ case SLJIT_EQUAL_F64:+ return 0x84 /* je */;++ case SLJIT_NOT_EQUAL:+ case SLJIT_NOT_EQUAL_F64:+ return 0x85 /* jne */;++ case SLJIT_LESS:+ case SLJIT_LESS_F64:+ return 0x82 /* jc */;++ case SLJIT_GREATER_EQUAL:+ case SLJIT_GREATER_EQUAL_F64:+ return 0x83 /* jae */;++ case SLJIT_GREATER:+ case SLJIT_GREATER_F64:+ return 0x87 /* jnbe */;++ case SLJIT_LESS_EQUAL:+ case SLJIT_LESS_EQUAL_F64:+ return 0x86 /* jbe */;++ case SLJIT_SIG_LESS:+ return 0x8c /* jl */;++ case SLJIT_SIG_GREATER_EQUAL:+ return 0x8d /* jnl */;++ case SLJIT_SIG_GREATER:+ return 0x8f /* jnle */;++ case SLJIT_SIG_LESS_EQUAL:+ return 0x8e /* jle */;++ case SLJIT_OVERFLOW:+ case SLJIT_MUL_OVERFLOW:+ return 0x80 /* jo */;++ case SLJIT_NOT_OVERFLOW:+ case SLJIT_MUL_NOT_OVERFLOW:+ return 0x81 /* jno */;++ case SLJIT_UNORDERED_F64:+ return 0x8a /* jp */;++ case SLJIT_ORDERED_F64:+ return 0x8b /* jpo */;+ }+ return 0;+}++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset);+#else+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr);+static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label);+#endif++static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)+{+ sljit_s32 type = jump->flags >> TYPE_SHIFT;+ sljit_s32 short_jump;+ sljit_uw label_addr;++ if (jump->flags & JUMP_LABEL)+ label_addr = (sljit_uw)(code + jump->u.label->size);+ else+ label_addr = jump->u.target - executable_offset;++ short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((sljit_sw)(label_addr - (jump->addr + 1)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump->addr + 1)) < HALFWORD_MIN)+ return generate_far_jump_code(jump, code_ptr);+#endif++ if (type == SLJIT_JUMP) {+ if (short_jump)+ *code_ptr++ = JMP_i8;+ else+ *code_ptr++ = JMP_i32;+ jump->addr++;+ }+ else if (type >= SLJIT_FAST_CALL) {+ short_jump = 0;+ *code_ptr++ = CALL_i32;+ jump->addr++;+ }+ else if (short_jump) {+ *code_ptr++ = get_jump_code(type) - 0x10;+ jump->addr++;+ }+ else {+ *code_ptr++ = GROUP_0F;+ *code_ptr++ = get_jump_code(type);+ jump->addr += 2;+ }++ if (short_jump) {+ jump->flags |= PATCH_MB;+ code_ptr += sizeof(sljit_s8);+ } else {+ jump->flags |= PATCH_MW;+ code_ptr += sizeof(sljit_s32);+ }++ return code_ptr;+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)+{+ struct sljit_memory_fragment *buf;+ sljit_u8 *code;+ sljit_u8 *code_ptr;+ sljit_u8 *buf_ptr;+ sljit_u8 *buf_end;+ sljit_u8 len;+ sljit_sw executable_offset;+ sljit_sw jump_addr;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ struct sljit_put_label *put_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler));+ reverse_buf(compiler);++ /* Second code generation pass. */+ code = (sljit_u8*)SLJIT_MALLOC_EXEC(compiler->size, compiler->exec_allocator_data);+ PTR_FAIL_WITH_EXEC_IF(code);+ buf = compiler->buf;++ code_ptr = code;+ label = compiler->labels;+ jump = compiler->jumps;+ const_ = compiler->consts;+ put_label = compiler->put_labels;+ executable_offset = SLJIT_EXEC_OFFSET(code);++ do {+ buf_ptr = buf->memory;+ buf_end = buf_ptr + buf->used_size;+ do {+ len = *buf_ptr++;+ if (len > 0) {+ /* The code is already generated. */+ SLJIT_MEMCPY(code_ptr, buf_ptr, len);+ code_ptr += len;+ buf_ptr += len;+ }+ else {+ switch (*buf_ptr) {+ case 0:+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ label->size = code_ptr - code;+ label = label->next;+ break;+ case 1:+ jump->addr = (sljit_uw)code_ptr;+ if (!(jump->flags & SLJIT_REWRITABLE_JUMP))+ code_ptr = generate_near_jump_code(jump, code_ptr, code, executable_offset);+ else {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ code_ptr = generate_far_jump_code(jump, code_ptr, executable_offset);+#else+ code_ptr = generate_far_jump_code(jump, code_ptr);+#endif+ }+ jump = jump->next;+ break;+ case 2:+ const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);+ const_ = const_->next;+ break;+ default:+ SLJIT_ASSERT(*buf_ptr == 3);+ SLJIT_ASSERT(put_label->label);+ put_label->addr = (sljit_uw)code_ptr;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ code_ptr = generate_put_label_code(put_label, code_ptr, (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size);+#endif+ put_label = put_label->next;+ break;+ }+ buf_ptr++;+ }+ } while (buf_ptr < buf_end);+ SLJIT_ASSERT(buf_ptr == buf_end);+ buf = buf->next;+ } while (buf);++ SLJIT_ASSERT(!label);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(!const_);+ SLJIT_ASSERT(!put_label);+ SLJIT_ASSERT(code_ptr <= code + compiler->size);++ jump = compiler->jumps;+ while (jump) {+ jump_addr = jump->addr + executable_offset;++ if (jump->flags & PATCH_MB) {+ SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) <= 127);+ *(sljit_u8*)jump->addr = (sljit_u8)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8)));+ } else if (jump->flags & PATCH_MW) {+ if (jump->flags & JUMP_LABEL) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_sw))));+#else+ SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX);+ sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))));+#endif+ }+ else {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_sw))));+#else+ SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX);+ sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.target - (jump_addr + sizeof(sljit_s32))));+#endif+ }+ }+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ else if (jump->flags & PATCH_MD)+ sljit_unaligned_store_sw((void*)jump->addr, jump->u.label->addr);+#endif++ jump = jump->next;+ }++ put_label = compiler->put_labels;+ while (put_label) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_unaligned_store_sw((void*)(put_label->addr - sizeof(sljit_sw)), (sljit_sw)put_label->label->addr);+#else+ if (put_label->flags & PATCH_MD) {+ SLJIT_ASSERT(put_label->label->addr > HALFWORD_MAX);+ sljit_unaligned_store_sw((void*)(put_label->addr - sizeof(sljit_sw)), (sljit_sw)put_label->label->addr);+ }+ else {+ SLJIT_ASSERT(put_label->label->addr <= HALFWORD_MAX);+ sljit_unaligned_store_s32((void*)(put_label->addr - sizeof(sljit_s32)), (sljit_s32)put_label->label->addr);+ }+#endif++ put_label = put_label->next;+ }++ compiler->error = SLJIT_ERR_COMPILED;+ compiler->executable_offset = executable_offset;+ compiler->executable_size = code_ptr - code;++ code = (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);++ SLJIT_UPDATE_WX_FLAGS(code, (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset), 1);+ return (void*)code;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)+{+ switch (feature_type) {+ case SLJIT_HAS_FPU:+#ifdef SLJIT_IS_FPU_AVAILABLE+ return SLJIT_IS_FPU_AVAILABLE;+#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)+ if (cpu_has_sse2 == -1)+ get_cpu_features();+ return cpu_has_sse2;+#else /* SLJIT_DETECT_SSE2 */+ return 1;+#endif /* SLJIT_DETECT_SSE2 */++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ case SLJIT_HAS_VIRTUAL_REGISTERS:+ return 1;+#endif++ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_CMOV:+ if (cpu_has_cmov == -1)+ get_cpu_features();+ return cpu_has_cmov;++ case SLJIT_HAS_PREFETCH:+ return 1;++ case SLJIT_HAS_SSE2:+#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)+ if (cpu_has_sse2 == -1)+ get_cpu_features();+ return cpu_has_sse2;+#else+ return 1;+#endif++ default:+ return 0;+ }+}++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++#define BINARY_OPCODE(opcode) (((opcode ## _EAX_i32) << 24) | ((opcode ## _r_rm) << 16) | ((opcode ## _rm_r) << 8) | (opcode))++static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,+ sljit_u32 op_types,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,+ sljit_u32 op_types,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++static sljit_s32 emit_mov(struct sljit_compiler *compiler,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw);++#define EMIT_MOV(compiler, dst, dstw, src, srcw) \+ FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));++static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler,+ sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src);++static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler,+ sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw);++static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w);++static SLJIT_INLINE sljit_s32 emit_endbranch(struct sljit_compiler *compiler)+{+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)+ /* Emit endbr32/endbr64 when CET is enabled. */+ sljit_u8 *inst;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ *inst++ = 0xf3;+ *inst++ = 0x0f;+ *inst++ = 0x1e;+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ *inst = 0xfb;+#else+ *inst = 0xfa;+#endif+#else /* !SLJIT_CONFIG_X86_CET */+ SLJIT_UNUSED_ARG(compiler);+#endif /* SLJIT_CONFIG_X86_CET */+ return SLJIT_SUCCESS;+}++#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)++static SLJIT_INLINE sljit_s32 emit_rdssp(struct sljit_compiler *compiler, sljit_s32 reg)+{+ sljit_u8 *inst;+ sljit_s32 size;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ size = 5;+#else+ size = 4;+#endif++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ *inst++ = 0xf3;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B);+#endif+ *inst++ = 0x0f;+ *inst++ = 0x1e;+ *inst = (0x3 << 6) | (0x1 << 3) | (reg_map[reg] & 0x7);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_incssp(struct sljit_compiler *compiler, sljit_s32 reg)+{+ sljit_u8 *inst;+ sljit_s32 size;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ size = 5;+#else+ size = 4;+#endif++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ *inst++ = 0xf3;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B);+#endif+ *inst++ = 0x0f;+ *inst++ = 0xae;+ *inst = (0x3 << 6) | (0x5 << 3) | (reg_map[reg] & 0x7);+ return SLJIT_SUCCESS;+}++#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */++static SLJIT_INLINE sljit_s32 cpu_has_shadow_stack(void)+{+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)+ return _get_ssp() != 0;+#else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */+ return 0;+#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */+}++static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compiler,+ sljit_s32 src, sljit_sw srcw, sljit_s32 base, sljit_sw disp)+{+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)+ sljit_u8 *inst, *jz_after_cmp_inst;+ sljit_uw size_jz_after_cmp_inst;++ sljit_uw size_before_rdssp_inst = compiler->size;++ /* Generate "RDSSP TMP_REG1". */+ FAIL_IF(emit_rdssp(compiler, TMP_REG1));++ /* Load return address on shadow stack into TMP_REG1. */+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ SLJIT_ASSERT(reg_map[TMP_REG1] == 5);++ /* Hand code unsupported "mov 0x0(%ebp),%ebp". */+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);+ FAIL_IF(!inst);+ INC_SIZE(3);+ *inst++ = 0x8b;+ *inst++ = 0x6d;+ *inst = 0;+#else /* !SLJIT_CONFIG_X86_32 */+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), 0);+#endif /* SLJIT_CONFIG_X86_32 */++ if (src == SLJIT_UNUSED) {+ /* Return address is on stack. */+ src = SLJIT_MEM1(base);+ srcw = disp;+ }++ /* Compare return address against TMP_REG1. */+ FAIL_IF(emit_cmp_binary (compiler, TMP_REG1, 0, src, srcw));++ /* Generate JZ to skip shadow stack ajdustment when shadow+ stack matches normal stack. */+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ *inst++ = get_jump_code(SLJIT_EQUAL) - 0x10;+ size_jz_after_cmp_inst = compiler->size;+ jz_after_cmp_inst = inst;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ /* REX_W is not necessary. */+ compiler->mode32 = 1;+#endif+ /* Load 1 into TMP_REG1. */+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1);++ /* Generate "INCSSP TMP_REG1". */+ FAIL_IF(emit_incssp(compiler, TMP_REG1));++ /* Jump back to "RDSSP TMP_REG1" to check shadow stack again. */+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ *inst++ = JMP_i8;+ *inst = size_before_rdssp_inst - compiler->size;++ *jz_after_cmp_inst = compiler->size - size_jz_after_cmp_inst;+#else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(src);+ SLJIT_UNUSED_ARG(srcw);+ SLJIT_UNUSED_ARG(base);+ SLJIT_UNUSED_ARG(disp);+#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */+ return SLJIT_SUCCESS;+}++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+#include "sljitNativeX86_32.c"+#else+#include "sljitNativeX86_64.c"+#endif++static sljit_s32 emit_mov(struct sljit_compiler *compiler,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;++ SLJIT_ASSERT(dst != SLJIT_UNUSED);++ if (FAST_IS_REG(src)) {+ inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_r;+ return SLJIT_SUCCESS;+ }+ if (src & SLJIT_IMM) {+ if (FAST_IS_REG(dst)) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);+#else+ if (!compiler->mode32) {+ if (NOT_HALFWORD(srcw))+ return emit_load_imm64(compiler, dst, srcw);+ }+ else+ return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, MOV_r_i32 + reg_lmap[dst], srcw);+#endif+ }+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (!compiler->mode32 && NOT_HALFWORD(srcw)) {+ /* Immediate to memory move. Only SLJIT_MOV operation copies+ an immediate directly into memory so TMP_REG1 can be used. */+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_r;+ return SLJIT_SUCCESS;+ }+#endif+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ return SLJIT_SUCCESS;+ }+ if (FAST_IS_REG(dst)) {+ inst = emit_x86_instruction(compiler, 1, dst, 0, src, srcw);+ FAIL_IF(!inst);+ *inst = MOV_r_rm;+ return SLJIT_SUCCESS;+ }++ /* Memory to memory move. Only SLJIT_MOV operation copies+ data from memory to memory so TMP_REG1 can be used. */+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw);+ FAIL_IF(!inst);+ *inst = MOV_r_rm;+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_r;+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)+{+ sljit_u8 *inst;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_s32 size;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op0(compiler, op));++ switch (GET_OPCODE(op)) {+ case SLJIT_BREAKPOINT:+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ *inst = INT3;+ break;+ case SLJIT_NOP:+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ *inst = NOP;+ break;+ case SLJIT_LMUL_UW:+ case SLJIT_LMUL_SW:+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIVMOD_SW:+ case SLJIT_DIV_UW:+ case SLJIT_DIV_SW:+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+#ifdef _WIN64+ SLJIT_ASSERT(+ reg_map[SLJIT_R0] == 0+ && reg_map[SLJIT_R1] == 2+ && reg_map[TMP_REG1] > 7);+#else+ SLJIT_ASSERT(+ reg_map[SLJIT_R0] == 0+ && reg_map[SLJIT_R1] < 7+ && reg_map[TMP_REG1] == 2);+#endif+ compiler->mode32 = op & SLJIT_I32_OP;+#endif+ SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);++ op = GET_OPCODE(op);+ if ((op | 0x2) == SLJIT_DIV_UW) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);+ inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0);+#else+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);+#endif+ FAIL_IF(!inst);+ *inst = XOR_r_rm;+ }++ if ((op | 0x2) == SLJIT_DIV_SW) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);+#endif++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ *inst = CDQ;+#else+ if (compiler->mode32) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ *inst = CDQ;+ } else {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ *inst++ = REX_W;+ *inst = CDQ;+ }+#endif+ }++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2);+ *inst++ = GROUP_F7;+ *inst = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);+#else+#ifdef _WIN64+ size = (!compiler->mode32 || op >= SLJIT_DIVMOD_UW) ? 3 : 2;+#else+ size = (!compiler->mode32) ? 3 : 2;+#endif+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+#ifdef _WIN64+ if (!compiler->mode32)+ *inst++ = REX_W | ((op >= SLJIT_DIVMOD_UW) ? REX_B : 0);+ else if (op >= SLJIT_DIVMOD_UW)+ *inst++ = REX_B;+ *inst++ = GROUP_F7;+ *inst = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);+#else+ if (!compiler->mode32)+ *inst++ = REX_W;+ *inst++ = GROUP_F7;+ *inst = MOD_REG | reg_map[SLJIT_R1];+#endif+#endif+ switch (op) {+ case SLJIT_LMUL_UW:+ *inst |= MUL;+ break;+ case SLJIT_LMUL_SW:+ *inst |= IMUL;+ break;+ case SLJIT_DIVMOD_UW:+ case SLJIT_DIV_UW:+ *inst |= DIV;+ break;+ case SLJIT_DIVMOD_SW:+ case SLJIT_DIV_SW:+ *inst |= IDIV;+ break;+ }+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)+ if (op <= SLJIT_DIVMOD_SW)+ EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);+#else+ if (op >= SLJIT_DIV_UW)+ EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);+#endif+ break;+ case SLJIT_ENDBR:+ return emit_endbranch(compiler);+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:+ return skip_frames_before_return(compiler);+ }++ return SLJIT_SUCCESS;+}++#define ENCODE_PREFIX(prefix) \+ do { \+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); \+ FAIL_IF(!inst); \+ INC_SIZE(1); \+ *inst = (prefix); \+ } while (0)++static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;+ sljit_s32 dst_r;+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_s32 work_r;+#endif++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+#endif++ if (src & SLJIT_IMM) {+ if (FAST_IS_REG(dst)) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);+#else+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ return SLJIT_SUCCESS;+#endif+ }+ inst = emit_x86_instruction(compiler, 1 | EX86_BYTE_ARG | EX86_NO_REXW, SLJIT_IMM, srcw, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm8_i8;+ return SLJIT_SUCCESS;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (reg_map[src] >= 4) {+ SLJIT_ASSERT(dst_r == TMP_REG1);+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);+ } else+ dst_r = src;+#else+ dst_r = src;+#endif+ }+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ else if (FAST_IS_REG(src) && reg_map[src] >= 4) {+ /* src, dst are registers. */+ SLJIT_ASSERT(SLOW_IS_REG(dst));+ if (reg_map[dst] < 4) {+ if (dst != src)+ EMIT_MOV(compiler, dst, 0, src, 0);+ inst = emit_x86_instruction(compiler, 2, dst, 0, dst, 0);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8;+ }+ else {+ if (dst != src)+ EMIT_MOV(compiler, dst, 0, src, 0);+ if (sign) {+ /* shl reg, 24 */+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);+ FAIL_IF(!inst);+ *inst |= SHL;+ /* sar reg, 24 */+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);+ FAIL_IF(!inst);+ *inst |= SAR;+ }+ else {+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0xff, dst, 0);+ FAIL_IF(!inst);+ *(inst + 1) |= AND;+ }+ }+ return SLJIT_SUCCESS;+ }+#endif+ else {+ /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8;+ }++ if (dst & SLJIT_MEM) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (dst_r == TMP_REG1) {+ /* Find a non-used register, whose reg_map[src] < 4. */+ if ((dst & REG_MASK) == SLJIT_R0) {+ if ((dst & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_R1))+ work_r = SLJIT_R2;+ else+ work_r = SLJIT_R1;+ }+ else {+ if ((dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R0))+ work_r = SLJIT_R0;+ else if ((dst & REG_MASK) == SLJIT_R1)+ work_r = SLJIT_R2;+ else+ work_r = SLJIT_R1;+ }++ if (work_r == SLJIT_R0) {+ ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REG1]);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);+ FAIL_IF(!inst);+ *inst = XCHG_r_rm;+ }++ inst = emit_x86_instruction(compiler, 1, work_r, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm8_r8;++ if (work_r == SLJIT_R0) {+ ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REG1]);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);+ FAIL_IF(!inst);+ *inst = XCHG_r_rm;+ }+ }+ else {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm8_r8;+ }+#else+ inst = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm8_r8;+#endif+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif++ inst = emit_x86_instruction(compiler, 2, 0, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst++ = PREFETCH;++ if (op == SLJIT_PREFETCH_L1)+ *inst |= (1 << 3);+ else if (op == SLJIT_PREFETCH_L2)+ *inst |= (2 << 3);+ else if (op == SLJIT_PREFETCH_L3)+ *inst |= (3 << 3);++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;+ sljit_s32 dst_r;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+#endif++ if (src & SLJIT_IMM) {+ if (FAST_IS_REG(dst)) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);+#else+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ return SLJIT_SUCCESS;+#endif+ }+ inst = emit_x86_instruction(compiler, 1 | EX86_HALF_ARG | EX86_NO_REXW | EX86_PREF_66, SLJIT_IMM, srcw, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ return SLJIT_SUCCESS;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if ((dst & SLJIT_MEM) && FAST_IS_REG(src))+ dst_r = src;+ else {+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = sign ? MOVSX_r_rm16 : MOVZX_r_rm16;+ }++ if (dst & SLJIT_MEM) {+ inst = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = MOV_rm_r;+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;++ if (dst == src && dstw == srcw) {+ /* Same input and output */+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst++ = GROUP_F7;+ *inst |= opcode;+ return SLJIT_SUCCESS;+ }++ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED))+ dst = TMP_REG1;++ if (FAST_IS_REG(dst)) {+ EMIT_MOV(compiler, dst, 0, src, srcw);+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);+ FAIL_IF(!inst);+ *inst++ = GROUP_F7;+ *inst |= opcode;+ return SLJIT_SUCCESS;+ }++ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst++ = GROUP_F7;+ *inst |= opcode;+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;++ if (dst == SLJIT_UNUSED)+ dst = TMP_REG1;++ if (FAST_IS_REG(dst)) {+ EMIT_MOV(compiler, dst, 0, src, srcw);+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);+ FAIL_IF(!inst);+ *inst++ = GROUP_F7;+ *inst |= NOT_rm;+ inst = emit_x86_instruction(compiler, 1, dst, 0, dst, 0);+ FAIL_IF(!inst);+ *inst = OR_r_rm;+ return SLJIT_SUCCESS;+ }++ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst++ = GROUP_F7;+ *inst |= NOT_rm;+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst = OR_r_rm;+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+}++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+static const sljit_sw emit_clz_arg = 32 + 31;+#endif++static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;+ sljit_s32 dst_r;++ SLJIT_UNUSED_ARG(op_flags);++ if (cpu_has_cmov == -1)+ get_cpu_features();++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = BSR_r_rm;++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (cpu_has_cmov) {+ if (dst_r != TMP_REG1) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 32 + 31);+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0);+ }+ else+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), (sljit_sw)&emit_clz_arg);++ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = CMOVE_r_rm;+ }+ else+ FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, 32 + 31));++ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);+#else+ if (cpu_has_cmov) {+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31));++ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = CMOVE_r_rm;+ }+ else+ FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31)));++ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 63 : 31, dst_r, 0);+#endif++ FAIL_IF(!inst);+ *(inst + 1) |= XOR;++ if (dst & SLJIT_MEM)+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 op_flags = GET_ALL_FLAGS(op);+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_s32 dst_is_ereg = 0;+#endif++ CHECK_ERROR();+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src, srcw);++ CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);+ CHECK_EXTRA_REGS(src, srcw, (void)0);+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = op_flags & SLJIT_I32_OP;+#endif++ op = GET_OPCODE(op);++ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+#endif++ if (FAST_IS_REG(src) && src == dst) {+ if (!TYPE_CAST_NEEDED(op))+ return SLJIT_SUCCESS;+ }++ if (op_flags & SLJIT_I32_OP) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (src & SLJIT_MEM) {+ if (op == SLJIT_MOV_S32)+ op = SLJIT_MOV_U32;+ }+ else if (src & SLJIT_IMM) {+ if (op == SLJIT_MOV_U32)+ op = SLJIT_MOV_S32;+ }+#endif+ }++ if (src & SLJIT_IMM) {+ switch (op) {+ case SLJIT_MOV_U8:+ srcw = (sljit_u8)srcw;+ break;+ case SLJIT_MOV_S8:+ srcw = (sljit_s8)srcw;+ break;+ case SLJIT_MOV_U16:+ srcw = (sljit_u16)srcw;+ break;+ case SLJIT_MOV_S16:+ srcw = (sljit_s16)srcw;+ break;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ case SLJIT_MOV_U32:+ srcw = (sljit_u32)srcw;+ break;+ case SLJIT_MOV_S32:+ srcw = (sljit_s32)srcw;+ break;+#endif+ }+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (SLJIT_UNLIKELY(dst_is_ereg))+ return emit_mov(compiler, dst, dstw, src, srcw);+#endif+ }++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) {+ SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_SP));+ dst = TMP_REG1;+ }+#endif++ switch (op) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+#endif+ FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));+ break;+ case SLJIT_MOV_U8:+ FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, srcw));+ break;+ case SLJIT_MOV_S8:+ FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, srcw));+ break;+ case SLJIT_MOV_U16:+ FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, srcw));+ break;+ case SLJIT_MOV_S16:+ FAIL_IF(emit_mov_half(compiler, 1, dst, dstw, src, srcw));+ break;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ case SLJIT_MOV_U32:+ FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, srcw));+ break;+ case SLJIT_MOV_S32:+ FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, srcw));+ break;+#endif+ }++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1)+ return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0);+#endif+ return SLJIT_SUCCESS;+ }++ switch (op) {+ case SLJIT_NOT:+ if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_Z))+ return emit_not_with_flags(compiler, dst, dstw, src, srcw);+ return emit_unary(compiler, NOT_rm, dst, dstw, src, srcw);++ case SLJIT_NEG:+ return emit_unary(compiler, NEG_rm, dst, dstw, src, srcw);++ case SLJIT_CLZ:+ return emit_clz(compiler, op_flags, dst, dstw, src, srcw);+ }++ return SLJIT_SUCCESS;+}++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)++#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \+ if (IS_HALFWORD(immw) || compiler->mode32) { \+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \+ FAIL_IF(!inst); \+ *(inst + 1) |= (op_imm); \+ } \+ else { \+ FAIL_IF(emit_load_imm64(compiler, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, immw)); \+ inst = emit_x86_instruction(compiler, 1, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, 0, arg, argw); \+ FAIL_IF(!inst); \+ *inst = (op_mr); \+ }++#define BINARY_EAX_IMM(op_eax_imm, immw) \+ FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (op_eax_imm), immw))++#else++#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \+ FAIL_IF(!inst); \+ *(inst + 1) |= (op_imm);++#define BINARY_EAX_IMM(op_eax_imm, immw) \+ FAIL_IF(emit_do_imm(compiler, (op_eax_imm), immw))++#endif++static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,+ sljit_u32 op_types,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_u8* inst;+ sljit_u8 op_eax_imm = (op_types >> 24);+ sljit_u8 op_rm = (op_types >> 16) & 0xff;+ sljit_u8 op_mr = (op_types >> 8) & 0xff;+ sljit_u8 op_imm = op_types & 0xff;++ if (dst == SLJIT_UNUSED) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ if (src2 & SLJIT_IMM) {+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ return SLJIT_SUCCESS;+ }++ if (dst == src1 && dstw == src1w) {+ if (src2 & SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {+#else+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) {+#endif+ BINARY_EAX_IMM(op_eax_imm, src2w);+ }+ else {+ BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);+ }+ }+ else if (FAST_IS_REG(dst)) {+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ else if (FAST_IS_REG(src2)) {+ /* Special exception for sljit_emit_op_flags. */+ inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ else {+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ return SLJIT_SUCCESS;+ }++ /* Only for cumulative operations. */+ if (dst == src2 && dstw == src2w) {+ if (src1 & SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {+#else+ if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128)) {+#endif+ BINARY_EAX_IMM(op_eax_imm, src1w);+ }+ else {+ BINARY_IMM(op_imm, op_mr, src1w, dst, dstw);+ }+ }+ else if (FAST_IS_REG(dst)) {+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ else if (FAST_IS_REG(src1)) {+ inst = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ else {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ return SLJIT_SUCCESS;+ }++ /* General version. */+ if (FAST_IS_REG(dst)) {+ EMIT_MOV(compiler, dst, 0, src1, src1w);+ if (src2 & SLJIT_IMM) {+ BINARY_IMM(op_imm, op_mr, src2w, dst, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ }+ else {+ /* This version requires less memory writing. */+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ if (src2 & SLJIT_IMM) {+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,+ sljit_u32 op_types,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_u8* inst;+ sljit_u8 op_eax_imm = (op_types >> 24);+ sljit_u8 op_rm = (op_types >> 16) & 0xff;+ sljit_u8 op_mr = (op_types >> 8) & 0xff;+ sljit_u8 op_imm = op_types & 0xff;++ if (dst == SLJIT_UNUSED) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ if (src2 & SLJIT_IMM) {+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ return SLJIT_SUCCESS;+ }++ if (dst == src1 && dstw == src1w) {+ if (src2 & SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {+#else+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) {+#endif+ BINARY_EAX_IMM(op_eax_imm, src2w);+ }+ else {+ BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);+ }+ }+ else if (FAST_IS_REG(dst)) {+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ else if (FAST_IS_REG(src2)) {+ inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ else {+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = op_mr;+ }+ return SLJIT_SUCCESS;+ }++ /* General version. */+ if (FAST_IS_REG(dst) && dst != src2) {+ EMIT_MOV(compiler, dst, 0, src1, src1w);+ if (src2 & SLJIT_IMM) {+ BINARY_IMM(op_imm, op_mr, src2w, dst, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ }+ else {+ /* This version requires less memory writing. */+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ if (src2 & SLJIT_IMM) {+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = op_rm;+ }+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_mul(struct sljit_compiler *compiler,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_u8* inst;+ sljit_s32 dst_r;++ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;++ /* Register destination. */+ if (dst_r == src1 && !(src2 & SLJIT_IMM)) {+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = IMUL_r_rm;+ }+ else if (dst_r == src2 && !(src1 & SLJIT_IMM)) {+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = IMUL_r_rm;+ }+ else if (src1 & SLJIT_IMM) {+ if (src2 & SLJIT_IMM) {+ EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, src2w);+ src2 = dst_r;+ src2w = 0;+ }++ if (src1w <= 127 && src1w >= -128) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = IMUL_r_rm_i8;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ *inst = (sljit_s8)src1w;+ }+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ else {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = IMUL_r_rm_i32;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ sljit_unaligned_store_sw(inst, src1w);+ }+#else+ else if (IS_HALFWORD(src1w)) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = IMUL_r_rm_i32;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ sljit_unaligned_store_s32(inst, (sljit_s32)src1w);+ }+ else {+ if (dst_r != src2)+ EMIT_MOV(compiler, dst_r, 0, src2, src2w);+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = IMUL_r_rm;+ }+#endif+ }+ else if (src2 & SLJIT_IMM) {+ /* Note: src1 is NOT immediate. */++ if (src2w <= 127 && src2w >= -128) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = IMUL_r_rm_i8;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1);+ *inst = (sljit_s8)src2w;+ }+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ else {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = IMUL_r_rm_i32;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ sljit_unaligned_store_sw(inst, src2w);+ }+#else+ else if (IS_HALFWORD(src2w)) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = IMUL_r_rm_i32;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4);+ sljit_unaligned_store_s32(inst, (sljit_s32)src2w);+ }+ else {+ if (dst_r != src1)+ EMIT_MOV(compiler, dst_r, 0, src1, src1w);+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = IMUL_r_rm;+ }+#endif+ }+ else {+ /* Neither argument is immediate. */+ if (ADDRESSING_DEPENDS_ON(src2, dst_r))+ dst_r = TMP_REG1;+ EMIT_MOV(compiler, dst_r, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = IMUL_r_rm;+ }++ if (dst & SLJIT_MEM)+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_u8* inst;+ sljit_s32 dst_r, done = 0;++ /* These cases better be left to handled by normal way. */+ if (dst == src1 && dstw == src1w)+ return SLJIT_ERR_UNSUPPORTED;+ if (dst == src2 && dstw == src2w)+ return SLJIT_ERR_UNSUPPORTED;++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (FAST_IS_REG(src1)) {+ if (FAST_IS_REG(src2)) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0);+ FAIL_IF(!inst);+ *inst = LEA_r_m;+ done = 1;+ }+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((src2 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src2w))) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (sljit_s32)src2w);+#else+ if (src2 & SLJIT_IMM) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w);+#endif+ FAIL_IF(!inst);+ *inst = LEA_r_m;+ done = 1;+ }+ }+ else if (FAST_IS_REG(src2)) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((src1 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src1w))) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (sljit_s32)src1w);+#else+ if (src1 & SLJIT_IMM) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w);+#endif+ FAIL_IF(!inst);+ *inst = LEA_r_m;+ done = 1;+ }+ }++ if (done) {+ if (dst_r == TMP_REG1)+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+ }+ return SLJIT_ERR_UNSUPPORTED;+}++static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_u8* inst;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {+#else+ if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {+#endif+ BINARY_EAX_IMM(CMP_EAX_i32, src2w);+ return SLJIT_SUCCESS;+ }++ if (FAST_IS_REG(src1)) {+ if (src2 & SLJIT_IMM) {+ BINARY_IMM(CMP, CMP_rm_r, src2w, src1, 0);+ }+ else {+ inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = CMP_r_rm;+ }+ return SLJIT_SUCCESS;+ }++ if (FAST_IS_REG(src2) && !(src1 & SLJIT_IMM)) {+ inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = CMP_rm_r;+ return SLJIT_SUCCESS;+ }++ if (src2 & SLJIT_IMM) {+ if (src1 & SLJIT_IMM) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ src1 = TMP_REG1;+ src1w = 0;+ }+ BINARY_IMM(CMP, CMP_rm_r, src2w, src1, src1w);+ }+ else {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = CMP_r_rm;+ }+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_test_binary(struct sljit_compiler *compiler,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_u8* inst;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {+#else+ if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {+#endif+ BINARY_EAX_IMM(TEST_EAX_i32, src2w);+ return SLJIT_SUCCESS;+ }++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {+#else+ if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) {+#endif+ BINARY_EAX_IMM(TEST_EAX_i32, src1w);+ return SLJIT_SUCCESS;+ }++ if (!(src1 & SLJIT_IMM)) {+ if (src2 & SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (IS_HALFWORD(src2w) || compiler->mode32) {+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+ }+ else {+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src2w));+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ }+#else+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+#endif+ return SLJIT_SUCCESS;+ }+ else if (FAST_IS_REG(src1)) {+ inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ return SLJIT_SUCCESS;+ }+ }++ if (!(src2 & SLJIT_IMM)) {+ if (src1 & SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (IS_HALFWORD(src1w) || compiler->mode32) {+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+ }+ else {+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src1w));+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ }+#else+ inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+#endif+ return SLJIT_SUCCESS;+ }+ else if (FAST_IS_REG(src2)) {+ inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ return SLJIT_SUCCESS;+ }+ }++ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ if (src2 & SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (IS_HALFWORD(src2w) || compiler->mode32) {+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+ }+ else {+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ }+#else+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst = GROUP_F7;+#endif+ }+ else {+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);+ FAIL_IF(!inst);+ *inst = TEST_rm_r;+ }+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_shift(struct sljit_compiler *compiler,+ sljit_u8 mode,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_u8* inst;++ if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) {+ if (dst == src1 && dstw == src1w) {+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw);+ FAIL_IF(!inst);+ *inst |= mode;+ return SLJIT_SUCCESS;+ }+ if (dst == SLJIT_UNUSED) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst |= mode;+ return SLJIT_SUCCESS;+ }+ if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst |= mode;+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ return SLJIT_SUCCESS;+ }+ if (FAST_IS_REG(dst)) {+ EMIT_MOV(compiler, dst, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0);+ FAIL_IF(!inst);+ *inst |= mode;+ return SLJIT_SUCCESS;+ }++ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst |= mode;+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+ }++ if (dst == SLJIT_PREF_SHIFT_REG) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst |= mode;+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ }+ else if (SLOW_IS_REG(dst) && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) {+ if (src1 != dst)+ EMIT_MOV(compiler, dst, 0, src1, src1w);+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0);+ FAIL_IF(!inst);+ *inst |= mode;+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ }+ else {+ /* This case is complex since ecx itself may be used for+ addressing, and this case must be supported as well. */+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0);+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst |= mode;+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0);+#else+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);+ FAIL_IF(!inst);+ *inst |= mode;+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);+#endif+ if (dst != SLJIT_UNUSED)+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);+ }++ return SLJIT_SUCCESS;+}++static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler,+ sljit_u8 mode, sljit_s32 set_flags,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ /* The CPU does not set flags if the shift count is 0. */+ if (src2 & SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((src2w & 0x3f) != 0 || (compiler->mode32 && (src2w & 0x1f) != 0))+ return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);+#else+ if ((src2w & 0x1f) != 0)+ return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);+#endif+ if (!set_flags)+ return emit_mov(compiler, dst, dstw, src1, src1w);+ /* OR dst, src, 0 */+ return emit_cum_binary(compiler, BINARY_OPCODE(OR),+ dst, dstw, src1, src1w, SLJIT_IMM, 0);+ }++ if (!set_flags)+ return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);++ if (!FAST_IS_REG(dst))+ FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0));++ FAIL_IF(emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w));++ if (FAST_IS_REG(dst))+ return emit_cmp_binary(compiler, (dst == SLJIT_UNUSED) ? TMP_REG1 : dst, dstw, SLJIT_IMM, 0);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);+ CHECK_EXTRA_REGS(src1, src1w, (void)0);+ CHECK_EXTRA_REGS(src2, src2w, (void)0);+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = op & SLJIT_I32_OP;+#endif++ if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))+ return SLJIT_SUCCESS;++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD:+ if (!HAS_FLAGS(op)) {+ if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)+ return compiler->error;+ }+ return emit_cum_binary(compiler, BINARY_OPCODE(ADD),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_ADDC:+ return emit_cum_binary(compiler, BINARY_OPCODE(ADC),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_SUB:+ if (!HAS_FLAGS(op)) {+ if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED)+ return compiler->error;+ if (SLOW_IS_REG(dst) && src2 == dst) {+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), dst, 0, dst, 0, src1, src1w));+ return emit_unary(compiler, NEG_rm, dst, 0, dst, 0);+ }+ }++ if (dst == SLJIT_UNUSED)+ return emit_cmp_binary(compiler, src1, src1w, src2, src2w);+ return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_SUBC:+ return emit_non_cum_binary(compiler, BINARY_OPCODE(SBB),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_MUL:+ return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_AND:+ if (dst == SLJIT_UNUSED)+ return emit_test_binary(compiler, src1, src1w, src2, src2w);+ return emit_cum_binary(compiler, BINARY_OPCODE(AND),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_OR:+ return emit_cum_binary(compiler, BINARY_OPCODE(OR),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_XOR:+ return emit_cum_binary(compiler, BINARY_OPCODE(XOR),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_SHL:+ return emit_shift_with_flags(compiler, SHL, HAS_FLAGS(op),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_LSHR:+ return emit_shift_with_flags(compiler, SHR, HAS_FLAGS(op),+ dst, dstw, src1, src1w, src2, src2w);+ case SLJIT_ASHR:+ return emit_shift_with_flags(compiler, SAR, HAS_FLAGS(op),+ dst, dstw, src1, src1w, src2, src2w);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ CHECK_EXTRA_REGS(src, srcw, (void)0);++ switch (op) {+ case SLJIT_FAST_RETURN:+ return emit_fast_return(compiler, src, srcw);+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:+ /* Don't adjust shadow stack if it isn't enabled. */+ if (!cpu_has_shadow_stack ())+ return SLJIT_SUCCESS;+ return adjust_shadow_stack(compiler, src, srcw, SLJIT_UNUSED, 0);+ case SLJIT_PREFETCH_L1:+ case SLJIT_PREFETCH_L2:+ case SLJIT_PREFETCH_L3:+ case SLJIT_PREFETCH_ONCE:+ return emit_prefetch(compiler, op, src, srcw);+ }++ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_register_index(reg));+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (reg >= SLJIT_R3 && reg <= SLJIT_R8)+ return -1;+#endif+ return reg_map[reg];+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)+{+ CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ return reg;+#else+ return freg_map[reg];+#endif+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,+ void *instruction, sljit_s32 size)+{+ sljit_u8 *inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ SLJIT_MEMCPY(inst, instruction, size);+ return SLJIT_SUCCESS;+}++/* --------------------------------------------------------------------- */+/* Floating point operators */+/* --------------------------------------------------------------------- */++/* Alignment(3) + 4 * 16 bytes. */+static sljit_s32 sse2_data[3 + (4 * 4)];+static sljit_s32 *sse2_buffer;++static void init_compiler(void)+{+ /* Align to 16 bytes. */+ sse2_buffer = (sljit_s32*)(((sljit_uw)sse2_data + 15) & ~0xf);++ /* Single precision constants (each constant is 16 byte long). */+ sse2_buffer[0] = 0x80000000;+ sse2_buffer[4] = 0x7fffffff;+ /* Double precision constants (each constant is 16 byte long). */+ sse2_buffer[8] = 0;+ sse2_buffer[9] = 0x80000000;+ sse2_buffer[12] = 0xffffffff;+ sse2_buffer[13] = 0x7fffffff;+}++static sljit_s32 emit_sse2(struct sljit_compiler *compiler, sljit_u8 opcode,+ sljit_s32 single, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w)+{+ sljit_u8 *inst;++ inst = emit_x86_instruction(compiler, 2 | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, xmm1, 0, xmm2, xmm2w);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = opcode;+ return SLJIT_SUCCESS;+}++static sljit_s32 emit_sse2_logic(struct sljit_compiler *compiler, sljit_u8 opcode,+ sljit_s32 pref66, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w)+{+ sljit_u8 *inst;++ inst = emit_x86_instruction(compiler, 2 | (pref66 ? EX86_PREF_66 : 0) | EX86_SSE2, xmm1, 0, xmm2, xmm2w);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = opcode;+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler,+ sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw)+{+ return emit_sse2(compiler, MOVSD_x_xm, single, dst, src, srcw);+}++static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler,+ sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src)+{+ return emit_sse2(compiler, MOVSD_xm_x, single, src, dst, dstw);+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ sljit_u8 *inst;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)+ compiler->mode32 = 0;+#endif++ inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_F32_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP2, dst_r, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = CVTTSD2SI_r_xm;++ if (dst & SLJIT_MEM)+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;+ sljit_u8 *inst;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)+ compiler->mode32 = 0;+#endif++ if (src & SLJIT_IMM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)+ srcw = (sljit_s32)srcw;+#endif+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);+ src = TMP_REG1;+ srcw = 0;+ }++ inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_F32_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP1, dst_r, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = CVTSI2SD_x_rm;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif+ if (dst_r == TMP_FREG)+ return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ if (!FAST_IS_REG(src1)) {+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));+ src1 = TMP_FREG;+ }++ return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_F32_OP), src1, src2, src2w);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_s32 dst_r;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif++ CHECK_ERROR();+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);++ if (GET_OPCODE(op) == SLJIT_MOV_F64) {+ if (FAST_IS_REG(dst))+ return emit_sse2_load(compiler, op & SLJIT_F32_OP, dst, src, srcw);+ if (FAST_IS_REG(src))+ return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, src);+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src, srcw));+ return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);+ }++ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) {+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;+ if (FAST_IS_REG(src)) {+ /* We overwrite the high bits of source. From SLJIT point of view,+ this is not an issue.+ Note: In SSE3, we could also use MOVDDUP and MOVSLDUP. */+ FAIL_IF(emit_sse2_logic(compiler, UNPCKLPD_x_xm, op & SLJIT_F32_OP, src, src, 0));+ }+ else {+ FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_F32_OP), TMP_FREG, src, srcw));+ src = TMP_FREG;+ }++ FAIL_IF(emit_sse2_logic(compiler, CVTPD2PS_x_xm, op & SLJIT_F32_OP, dst_r, src, 0));+ if (dst_r == TMP_FREG)+ return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+ }++ if (FAST_IS_REG(dst)) {+ dst_r = dst;+ if (dst != src)+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src, srcw));+ }+ else {+ dst_r = TMP_FREG;+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src, srcw));+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_NEG_F64:+ FAIL_IF(emit_sse2_logic(compiler, XORPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_F32_OP ? sse2_buffer : sse2_buffer + 8)));+ break;++ case SLJIT_ABS_F64:+ FAIL_IF(emit_sse2_logic(compiler, ANDPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_F32_OP ? sse2_buffer + 4 : sse2_buffer + 12)));+ break;+ }++ if (dst_r == TMP_FREG)+ return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 src1, sljit_sw src1w,+ sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 dst_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif++ if (FAST_IS_REG(dst)) {+ dst_r = dst;+ if (dst == src1)+ ; /* Do nothing here. */+ else if (dst == src2 && (op == SLJIT_ADD_F64 || op == SLJIT_MUL_F64)) {+ /* Swap arguments. */+ src2 = src1;+ src2w = src1w;+ }+ else if (dst != src2)+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src1, src1w));+ else {+ dst_r = TMP_FREG;+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));+ }+ }+ else {+ dst_r = TMP_FREG;+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_ADD_F64:+ FAIL_IF(emit_sse2(compiler, ADDSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));+ break;++ case SLJIT_SUB_F64:+ FAIL_IF(emit_sse2(compiler, SUBSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));+ break;++ case SLJIT_MUL_F64:+ FAIL_IF(emit_sse2(compiler, MULSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));+ break;++ case SLJIT_DIV_F64:+ FAIL_IF(emit_sse2(compiler, DIVSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));+ break;+ }++ if (dst_r == TMP_FREG)+ return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);+ return SLJIT_SUCCESS;+}++/* --------------------------------------------------------------------- */+/* Conditional instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)+{+ sljit_u8 *inst;+ struct sljit_label *label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_label(compiler));++ if (compiler->last_label && compiler->last_label->size == compiler->size)+ return compiler->last_label;++ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ PTR_FAIL_IF(!label);+ set_label(label, compiler);++ inst = (sljit_u8*)ensure_buf(compiler, 2);+ PTR_FAIL_IF(!inst);++ *inst++ = 0;+ *inst++ = 0;++ return label;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)+{+ sljit_u8 *inst;+ struct sljit_jump *jump;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_jump(compiler, type));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF_NULL(jump);+ set_jump(jump, compiler, (type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT));+ type &= 0xff;++ /* Worst case size. */+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ compiler->size += (type >= SLJIT_JUMP) ? 5 : 6;+#else+ compiler->size += (type >= SLJIT_JUMP) ? (10 + 3) : (2 + 10 + 3);+#endif++ inst = (sljit_u8*)ensure_buf(compiler, 2);+ PTR_FAIL_IF_NULL(inst);++ *inst++ = 0;+ *inst++ = 1;+ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)+{+ sljit_u8 *inst;+ struct sljit_jump *jump;++ CHECK_ERROR();+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));+ ADJUST_LOCAL_OFFSET(src, srcw);++ CHECK_EXTRA_REGS(src, srcw, (void)0);++ if (src == SLJIT_IMM) {+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF_NULL(jump);+ set_jump(jump, compiler, JUMP_ADDR | (type << TYPE_SHIFT));+ jump->u.target = srcw;++ /* Worst case size. */+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ compiler->size += 5;+#else+ compiler->size += 10 + 3;+#endif++ inst = (sljit_u8*)ensure_buf(compiler, 2);+ FAIL_IF_NULL(inst);++ *inst++ = 0;+ *inst++ = 1;+ }+ else {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ /* REX_W is not necessary (src is not immediate). */+ compiler->mode32 = 1;+#endif+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = GROUP_FF;+ *inst |= (type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm;+ }+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_s32 type)+{+ sljit_u8 *inst;+ sljit_u8 cond_set = 0;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_s32 reg;+#endif+ /* ADJUST_LOCAL_OFFSET and CHECK_EXTRA_REGS might overwrite these values. */+ sljit_s32 dst_save = dst;+ sljit_sw dstw_save = dstw;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));++ ADJUST_LOCAL_OFFSET(dst, dstw);+ CHECK_EXTRA_REGS(dst, dstw, (void)0);++ type &= 0xff;+ /* setcc = jcc + 0x10. */+ cond_set = get_jump_code(type) + 0x10;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst)) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 3);+ FAIL_IF(!inst);+ INC_SIZE(4 + 3);+ /* Set low register to conditional flag. */+ *inst++ = (reg_map[TMP_REG1] <= 7) ? REX : REX_B;+ *inst++ = GROUP_0F;+ *inst++ = cond_set;+ *inst++ = MOD_REG | reg_lmap[TMP_REG1];+ *inst++ = REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B);+ *inst++ = OR_rm8_r8;+ *inst++ = MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst];+ return SLJIT_SUCCESS;+ }++ reg = (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG1;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 4);+ FAIL_IF(!inst);+ INC_SIZE(4 + 4);+ /* Set low register to conditional flag. */+ *inst++ = (reg_map[reg] <= 7) ? REX : REX_B;+ *inst++ = GROUP_0F;+ *inst++ = cond_set;+ *inst++ = MOD_REG | reg_lmap[reg];+ *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R));+ /* The movzx instruction does not affect flags. */+ *inst++ = GROUP_0F;+ *inst++ = MOVZX_r_rm8;+ *inst = MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg];++ if (reg != TMP_REG1)+ return SLJIT_SUCCESS;++ if (GET_OPCODE(op) < SLJIT_ADD) {+ compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV;+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);+ }++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);++#else+ /* The SLJIT_CONFIG_X86_32 code path starts here. */+ if (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) {+ if (reg_map[dst] <= 4) {+ /* Low byte is accessible. */+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 3);+ FAIL_IF(!inst);+ INC_SIZE(3 + 3);+ /* Set low byte to conditional flag. */+ *inst++ = GROUP_0F;+ *inst++ = cond_set;+ *inst++ = MOD_REG | reg_map[dst];++ *inst++ = GROUP_0F;+ *inst++ = MOVZX_r_rm8;+ *inst = MOD_REG | (reg_map[dst] << 3) | reg_map[dst];+ return SLJIT_SUCCESS;+ }++ /* Low byte is not accessible. */+ if (cpu_has_cmov == -1)+ get_cpu_features();++ if (cpu_has_cmov) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1);+ /* a xor reg, reg operation would overwrite the flags. */+ EMIT_MOV(compiler, dst, 0, SLJIT_IMM, 0);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);+ FAIL_IF(!inst);+ INC_SIZE(3);++ *inst++ = GROUP_0F;+ /* cmovcc = setcc - 0x50. */+ *inst++ = cond_set - 0x50;+ *inst++ = MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REG1];+ return SLJIT_SUCCESS;+ }++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1 + 3 + 3 + 1);+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];+ /* Set al to conditional flag. */+ *inst++ = GROUP_0F;+ *inst++ = cond_set;+ *inst++ = MOD_REG | 0 /* eax */;++ *inst++ = GROUP_0F;+ *inst++ = MOVZX_r_rm8;+ *inst++ = MOD_REG | (reg_map[dst] << 3) | 0 /* eax */;+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];+ return SLJIT_SUCCESS;+ }++ if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && reg_map[dst] <= 4) {+ SLJIT_ASSERT(reg_map[SLJIT_R0] == 0);++ if (dst != SLJIT_R0) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1 + 3 + 2 + 1);+ /* Set low register to conditional flag. */+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];+ *inst++ = GROUP_0F;+ *inst++ = cond_set;+ *inst++ = MOD_REG | 0 /* eax */;+ *inst++ = OR_rm8_r8;+ *inst++ = MOD_REG | (0 /* eax */ << 3) | reg_map[dst];+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];+ }+ else {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 3 + 2 + 2);+ FAIL_IF(!inst);+ INC_SIZE(2 + 3 + 2 + 2);+ /* Set low register to conditional flag. */+ *inst++ = XCHG_r_rm;+ *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1];+ *inst++ = GROUP_0F;+ *inst++ = cond_set;+ *inst++ = MOD_REG | 1 /* ecx */;+ *inst++ = OR_rm8_r8;+ *inst++ = MOD_REG | (1 /* ecx */ << 3) | 0 /* eax */;+ *inst++ = XCHG_r_rm;+ *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1];+ }+ return SLJIT_SUCCESS;+ }++ /* Set TMP_REG1 to the bit. */+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);+ FAIL_IF(!inst);+ INC_SIZE(1 + 3 + 3 + 1);+ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];+ /* Set al to conditional flag. */+ *inst++ = GROUP_0F;+ *inst++ = cond_set;+ *inst++ = MOD_REG | 0 /* eax */;++ *inst++ = GROUP_0F;+ *inst++ = MOVZX_r_rm8;+ *inst++ = MOD_REG | (0 << 3) /* eax */ | 0 /* eax */;++ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];++ if (GET_OPCODE(op) < SLJIT_ADD)+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->skip_checks = 1;+#endif+ return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);+#endif /* SLJIT_CONFIG_X86_64 */+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_reg,+ sljit_s32 src, sljit_sw srcw)+{+ sljit_u8* inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ dst_reg &= ~SLJIT_I32_OP;++ if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV) || (dst_reg >= SLJIT_R3 && dst_reg <= SLJIT_S3))+ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);+#else+ if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV))+ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);+#endif++ /* ADJUST_LOCAL_OFFSET is not needed. */+ CHECK_EXTRA_REGS(src, srcw, (void)0);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = dst_reg & SLJIT_I32_OP;+ dst_reg &= ~SLJIT_I32_OP;+#endif++ if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);+ src = TMP_REG1;+ srcw = 0;+ }++ inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw);+ FAIL_IF(!inst);+ *inst++ = GROUP_0F;+ *inst = get_jump_code(type & 0xff) - 0x40;+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)+{+ CHECK_ERROR();+ CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+#endif++ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (NOT_HALFWORD(offset)) {+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, offset));+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ SLJIT_ASSERT(emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);+ return compiler->error;+#else+ return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0);+#endif+ }+#endif++ if (offset != 0)+ return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);+ return emit_mov(compiler, dst, dstw, SLJIT_SP, 0);+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)+{+ sljit_u8 *inst;+ struct sljit_const *const_;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_s32 reg;+#endif++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (emit_load_imm64(compiler, reg, init_value))+ return NULL;+#else+ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value))+ return NULL;+#endif++ inst = (sljit_u8*)ensure_buf(compiler, 2);+ PTR_FAIL_IF(!inst);++ *inst++ = 0;+ *inst++ = 2;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (dst & SLJIT_MEM)+ if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))+ return NULL;+#endif++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_put_label *put_label;+ sljit_u8 *inst;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_s32 reg;+ sljit_uw start_size;+#endif++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);++ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));+ PTR_FAIL_IF(!put_label);+ set_put_label(put_label, compiler, 0);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (emit_load_imm64(compiler, reg, 0))+ return NULL;+#else+ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, 0))+ return NULL;+#endif++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (dst & SLJIT_MEM) {+ start_size = compiler->size;+ if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))+ return NULL;+ put_label->flags = compiler->size - start_size;+ }+#endif++ inst = (sljit_u8*)ensure_buf(compiler, 2);+ PTR_FAIL_IF(!inst);++ *inst++ = 0;+ *inst++ = 3;++ return put_label;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)+{+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 0);+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_unaligned_store_sw((void*)addr, new_target - (addr + 4) - (sljit_uw)executable_offset);+#else+ sljit_unaligned_store_sw((void*)addr, (sljit_sw) new_target);+#endif+ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 1);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)+{+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_sw)), 0);+ sljit_unaligned_store_sw((void*)addr, new_constant);+ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_sw)), 1);+}
+ src/c/pcre2/src/sljit/sljitProtExecAllocator.c view
@@ -0,0 +1,474 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/*+ This file contains a simple executable memory allocator++ It is assumed, that executable code blocks are usually medium (or sometimes+ large) memory blocks, and the allocator is not too frequently called (less+ optimized than other allocators). Thus, using it as a generic allocator is+ not suggested.++ How does it work:+ Memory is allocated in continuous memory areas called chunks by alloc_chunk()+ Chunk format:+ [ block ][ block ] ... [ block ][ block terminator ]++ All blocks and the block terminator is started with block_header. The block+ header contains the size of the previous and the next block. These sizes+ can also contain special values.+ Block size:+ 0 - The block is a free_block, with a different size member.+ 1 - The block is a block terminator.+ n - The block is used at the moment, and the value contains its size.+ Previous block size:+ 0 - This is the first block of the memory chunk.+ n - The size of the previous block.++ Using these size values we can go forward or backward on the block chain.+ The unused blocks are stored in a chain list pointed by free_blocks. This+ list is useful if we need to find a suitable memory area when the allocator+ is called.++ When a block is freed, the new free block is connected to its adjacent free+ blocks if possible.++ [ free block ][ used block ][ free block ]+ and "used block" is freed, the three blocks are connected together:+ [ one big free block ]+*/++/* --------------------------------------------------------------------- */+/* System (OS) functions */+/* --------------------------------------------------------------------- */++/* 64 KByte. */+#define CHUNK_SIZE 0x10000++struct chunk_header {+ void *executable;+};++/*+ alloc_chunk / free_chunk :+ * allocate executable system memory chunks+ * the size is always divisible by CHUNK_SIZE+ SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK :+ * provided as part of sljitUtils+ * only the allocator requires this lock, sljit is fully thread safe+ as it only uses local variables+*/++#ifndef __NetBSD__+#include <sys/stat.h>+#include <fcntl.h>+#include <stdio.h>+#include <string.h>++#ifndef O_NOATIME+#define O_NOATIME 0+#endif++/* this is a linux extension available since kernel 3.11 */+#ifndef O_TMPFILE+#define O_TMPFILE 020200000+#endif++#ifndef _GNU_SOURCE+char *secure_getenv(const char *name);+int mkostemp(char *template, int flags);+#endif++static SLJIT_INLINE int create_tempfile(void)+{+ int fd;+ char tmp_name[256];+ size_t tmp_name_len = 0;+ char *dir;+ struct stat st;+#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED+ mode_t mode;+#endif++#ifdef HAVE_MEMFD_CREATE+ /* this is a GNU extension, make sure to use -D_GNU_SOURCE */+ fd = memfd_create("sljit", MFD_CLOEXEC);+ if (fd != -1) {+ fchmod(fd, 0);+ return fd;+ }+#endif++ dir = secure_getenv("TMPDIR");++ if (dir) {+ tmp_name_len = strlen(dir);+ if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)) {+ if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode))+ strcpy(tmp_name, dir);+ }+ }++#ifdef P_tmpdir+ if (!tmp_name_len) {+ tmp_name_len = strlen(P_tmpdir);+ if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name))+ strcpy(tmp_name, P_tmpdir);+ }+#endif+ if (!tmp_name_len) {+ strcpy(tmp_name, "/tmp");+ tmp_name_len = 4;+ }++ SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name));++ if (tmp_name[tmp_name_len - 1] == '/')+ tmp_name[--tmp_name_len] = '\0';++#ifdef __linux__+ /*+ * the previous trimming might had left an empty string if TMPDIR="/"+ * so work around the problem below+ */+ fd = open(tmp_name_len ? tmp_name : "/",+ O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0);+ if (fd != -1)+ return fd;+#endif++ if (tmp_name_len + 7 >= sizeof(tmp_name))+ return -1;++ strcpy(tmp_name + tmp_name_len, "/XXXXXX");+#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED+ mode = umask(0777);+#endif+ fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME);+#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED+ umask(mode);+#else+ fchmod(fd, 0);+#endif++ if (fd == -1)+ return -1;++ if (unlink(tmp_name)) {+ close(fd);+ return -1;+ }++ return fd;+}++static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size)+{+ struct chunk_header *retval;+ int fd;++ fd = create_tempfile();+ if (fd == -1)+ return NULL;++ if (ftruncate(fd, size)) {+ close(fd);+ return NULL;+ }++ retval = (struct chunk_header *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);++ if (retval == MAP_FAILED) {+ close(fd);+ return NULL;+ }++ retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);++ if (retval->executable == MAP_FAILED) {+ munmap((void *)retval, size);+ close(fd);+ return NULL;+ }++ close(fd);+ return retval;+}+#else+/*+ * MAP_REMAPDUP is a NetBSD extension available sinde 8.0, make sure to+ * adjust your feature macros (ex: -D_NETBSD_SOURCE) as needed+ */+static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size)+{+ struct chunk_header *retval;++ retval = (struct chunk_header *)mmap(NULL, size,+ PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC),+ MAP_ANON | MAP_SHARED, -1, 0);++ if (retval == MAP_FAILED)+ return NULL;++ retval->executable = mremap(retval, size, NULL, size, MAP_REMAPDUP);+ if (retval->executable == MAP_FAILED) {+ munmap((void *)retval, size);+ return NULL;+ }++ if (mprotect(retval->executable, size, PROT_READ | PROT_EXEC) == -1) {+ munmap(retval->executable, size);+ munmap((void *)retval, size);+ return NULL;+ }++ return retval;+}+#endif /* NetBSD */++static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)+{+ struct chunk_header *header = ((struct chunk_header *)chunk) - 1;++ munmap(header->executable, size);+ munmap((void *)header, size);+}++/* --------------------------------------------------------------------- */+/* Common functions */+/* --------------------------------------------------------------------- */++#define CHUNK_MASK (~(CHUNK_SIZE - 1))++struct block_header {+ sljit_uw size;+ sljit_uw prev_size;+ sljit_sw executable_offset;+};++struct free_block {+ struct block_header header;+ struct free_block *next;+ struct free_block *prev;+ sljit_uw size;+};++#define AS_BLOCK_HEADER(base, offset) \+ ((struct block_header*)(((sljit_u8*)base) + offset))+#define AS_FREE_BLOCK(base, offset) \+ ((struct free_block*)(((sljit_u8*)base) + offset))+#define MEM_START(base) ((void*)((base) + 1))+#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7)++static struct free_block* free_blocks;+static sljit_uw allocated_size;+static sljit_uw total_size;++static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)+{+ free_block->header.size = 0;+ free_block->size = size;++ free_block->next = free_blocks;+ free_block->prev = NULL;+ if (free_blocks)+ free_blocks->prev = free_block;+ free_blocks = free_block;+}++static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)+{+ if (free_block->next)+ free_block->next->prev = free_block->prev;++ if (free_block->prev)+ free_block->prev->next = free_block->next;+ else {+ SLJIT_ASSERT(free_blocks == free_block);+ free_blocks = free_block->next;+ }+}++SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)+{+ struct chunk_header *chunk_header;+ struct block_header *header;+ struct block_header *next_header;+ struct free_block *free_block;+ sljit_uw chunk_size;+ sljit_sw executable_offset;++ SLJIT_ALLOCATOR_LOCK();+ if (size < (64 - sizeof(struct block_header)))+ size = (64 - sizeof(struct block_header));+ size = ALIGN_SIZE(size);++ free_block = free_blocks;+ while (free_block) {+ if (free_block->size >= size) {+ chunk_size = free_block->size;+ if (chunk_size > size + 64) {+ /* We just cut a block from the end of the free block. */+ chunk_size -= size;+ free_block->size = chunk_size;+ header = AS_BLOCK_HEADER(free_block, chunk_size);+ header->prev_size = chunk_size;+ header->executable_offset = free_block->header.executable_offset;+ AS_BLOCK_HEADER(header, size)->prev_size = size;+ }+ else {+ sljit_remove_free_block(free_block);+ header = (struct block_header*)free_block;+ size = chunk_size;+ }+ allocated_size += size;+ header->size = size;+ SLJIT_ALLOCATOR_UNLOCK();+ return MEM_START(header);+ }+ free_block = free_block->next;+ }++ chunk_size = sizeof(struct chunk_header) + sizeof(struct block_header);+ chunk_size = (chunk_size + size + CHUNK_SIZE - 1) & CHUNK_MASK;++ chunk_header = alloc_chunk(chunk_size);+ if (!chunk_header) {+ SLJIT_ALLOCATOR_UNLOCK();+ return NULL;+ }++ executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (sljit_u8*)chunk_header);++ chunk_size -= sizeof(struct chunk_header) + sizeof(struct block_header);+ total_size += chunk_size;++ header = (struct block_header *)(chunk_header + 1);++ header->prev_size = 0;+ header->executable_offset = executable_offset;+ if (chunk_size > size + 64) {+ /* Cut the allocated space into a free and a used block. */+ allocated_size += size;+ header->size = size;+ chunk_size -= size;++ free_block = AS_FREE_BLOCK(header, size);+ free_block->header.prev_size = size;+ free_block->header.executable_offset = executable_offset;+ sljit_insert_free_block(free_block, chunk_size);+ next_header = AS_BLOCK_HEADER(free_block, chunk_size);+ }+ else {+ /* All space belongs to this allocation. */+ allocated_size += chunk_size;+ header->size = chunk_size;+ next_header = AS_BLOCK_HEADER(header, chunk_size);+ }+ next_header->size = 1;+ next_header->prev_size = chunk_size;+ next_header->executable_offset = executable_offset;+ SLJIT_ALLOCATOR_UNLOCK();+ return MEM_START(header);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)+{+ struct block_header *header;+ struct free_block* free_block;++ SLJIT_ALLOCATOR_LOCK();+ header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));+ header = AS_BLOCK_HEADER(header, -header->executable_offset);+ allocated_size -= header->size;++ /* Connecting free blocks together if possible. */++ /* If header->prev_size == 0, free_block will equal to header.+ In this case, free_block->header.size will be > 0. */+ free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);+ if (SLJIT_UNLIKELY(!free_block->header.size)) {+ free_block->size += header->size;+ header = AS_BLOCK_HEADER(free_block, free_block->size);+ header->prev_size = free_block->size;+ }+ else {+ free_block = (struct free_block*)header;+ sljit_insert_free_block(free_block, header->size);+ }++ header = AS_BLOCK_HEADER(free_block, free_block->size);+ if (SLJIT_UNLIKELY(!header->size)) {+ free_block->size += ((struct free_block*)header)->size;+ sljit_remove_free_block((struct free_block*)header);+ header = AS_BLOCK_HEADER(free_block, free_block->size);+ header->prev_size = free_block->size;+ }++ /* The whole chunk is free. */+ if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {+ /* If this block is freed, we still have (allocated_size / 2) free space. */+ if (total_size - free_block->size > (allocated_size * 3 / 2)) {+ total_size -= free_block->size;+ sljit_remove_free_block(free_block);+ free_chunk(free_block, free_block->size ++ sizeof(struct chunk_header) ++ sizeof(struct block_header));+ }+ }++ SLJIT_ALLOCATOR_UNLOCK();+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)+{+ struct free_block* free_block;+ struct free_block* next_free_block;++ SLJIT_ALLOCATOR_LOCK();++ free_block = free_blocks;+ while (free_block) {+ next_free_block = free_block->next;+ if (!free_block->header.prev_size && + AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {+ total_size -= free_block->size;+ sljit_remove_free_block(free_block);+ free_chunk(free_block, free_block->size ++ sizeof(struct chunk_header) ++ sizeof(struct block_header));+ }+ free_block = next_free_block;+ }++ SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks));+ SLJIT_ALLOCATOR_UNLOCK();+}++SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr)+{+ return ((struct block_header *)(ptr))[-1].executable_offset;+}
+ src/c/pcre2/src/sljit/sljitUtils.c view
@@ -0,0 +1,337 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/* ------------------------------------------------------------------------ */+/* Locks */+/* ------------------------------------------------------------------------ */++/* Executable Allocator */++#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \+ && !(defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)+#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)+#define SLJIT_ALLOCATOR_LOCK()+#define SLJIT_ALLOCATOR_UNLOCK()+#elif !(defined _WIN32)+#include <pthread.h>++static pthread_mutex_t allocator_lock = PTHREAD_MUTEX_INITIALIZER;++#define SLJIT_ALLOCATOR_LOCK() pthread_mutex_lock(&allocator_lock)+#define SLJIT_ALLOCATOR_UNLOCK() pthread_mutex_unlock(&allocator_lock)+#else /* windows */+static HANDLE allocator_lock;++static SLJIT_INLINE void allocator_grab_lock(void)+{+ HANDLE lock;+ if (SLJIT_UNLIKELY(!allocator_lock)) {+ lock = CreateMutex(NULL, FALSE, NULL);+ if (InterlockedCompareExchangePointer(&allocator_lock, lock, NULL))+ CloseHandle(lock);+ }+ WaitForSingleObject(allocator_lock, INFINITE);+}++#define SLJIT_ALLOCATOR_LOCK() allocator_grab_lock()+#define SLJIT_ALLOCATOR_UNLOCK() ReleaseMutex(allocator_lock)+#endif /* thread implementation */+#endif /* SLJIT_EXECUTABLE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */++/* ------------------------------------------------------------------------ */+/* Stack */+/* ------------------------------------------------------------------------ */++#if ((defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \+ && !(defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)) \+ || ((defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \+ && !((defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) \+ || (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)))++#ifndef _WIN32+/* Provides mmap function. */+#include <sys/types.h>+#include <sys/mman.h>++#ifndef MAP_ANON+#ifdef MAP_ANONYMOUS+#define MAP_ANON MAP_ANONYMOUS+#endif /* MAP_ANONYMOUS */+#endif /* !MAP_ANON */++#ifndef MAP_ANON++#include <fcntl.h>++#ifdef O_CLOEXEC+#define SLJIT_CLOEXEC O_CLOEXEC+#else /* !O_CLOEXEC */+#define SLJIT_CLOEXEC 0+#endif /* O_CLOEXEC */++/* Some old systems do not have MAP_ANON. */+static int dev_zero = -1;++#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)++static SLJIT_INLINE int open_dev_zero(void)+{+ dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);++ return dev_zero < 0;+}++#else /* !SLJIT_SINGLE_THREADED */++#include <pthread.h>++static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;++static SLJIT_INLINE int open_dev_zero(void)+{+ pthread_mutex_lock(&dev_zero_mutex);+ if (SLJIT_UNLIKELY(dev_zero < 0))+ dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);++ pthread_mutex_unlock(&dev_zero_mutex);+ return dev_zero < 0;+}++#endif /* SLJIT_SINGLE_THREADED */+#undef SLJIT_CLOEXEC+#endif /* !MAP_ANON */+#endif /* !_WIN32 */+#endif /* open_dev_zero */++#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \+ || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)++#ifdef _WIN32++static SLJIT_INLINE sljit_sw get_page_alignment(void) {+ SYSTEM_INFO si;+ static sljit_sw sljit_page_align;+ if (!sljit_page_align) {+ GetSystemInfo(&si);+ sljit_page_align = si.dwPageSize - 1;+ }+ return sljit_page_align;+}++#else++#include <unistd.h>++static SLJIT_INLINE sljit_sw get_page_alignment(void) {+ static sljit_sw sljit_page_align;+ if (!sljit_page_align) {+ sljit_page_align = sysconf(_SC_PAGESIZE);+ /* Should never happen. */+ if (sljit_page_align < 0)+ sljit_page_align = 4096;+ sljit_page_align--;+ }+ return sljit_page_align;+}++#endif /* _WIN32 */++#endif /* get_page_alignment() */++#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)++#if (defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)++SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)+{+ struct sljit_stack *stack;+ void *ptr;++ SLJIT_UNUSED_ARG(allocator_data);++ if (start_size > max_size || start_size < 1)+ return NULL;++ stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);+ if (stack == NULL)+ return NULL;++ ptr = SLJIT_MALLOC(max_size, allocator_data);+ if (ptr == NULL) {+ SLJIT_FREE(stack, allocator_data);+ return NULL;+ }++ stack->min_start = (sljit_u8 *)ptr;+ stack->end = stack->min_start + max_size;+ stack->start = stack->end - start_size;+ stack->top = stack->end;+ return stack;+}++SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)+{+ SLJIT_UNUSED_ARG(allocator_data);+ SLJIT_FREE((void*)stack->min_start, allocator_data);+ SLJIT_FREE(stack, allocator_data);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)+{+ if ((new_start < stack->min_start) || (new_start >= stack->end))+ return NULL;+ stack->start = new_start;+ return new_start;+}++#else /* !SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */++#ifdef _WIN32++SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)+{+ SLJIT_UNUSED_ARG(allocator_data);+ VirtualFree((void*)stack->min_start, 0, MEM_RELEASE);+ SLJIT_FREE(stack, allocator_data);+}++#else /* !_WIN32 */++SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)+{+ SLJIT_UNUSED_ARG(allocator_data);+ munmap((void*)stack->min_start, stack->end - stack->min_start);+ SLJIT_FREE(stack, allocator_data);+}++#endif /* _WIN32 */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)+{+ struct sljit_stack *stack;+ void *ptr;+ sljit_sw page_align;++ SLJIT_UNUSED_ARG(allocator_data);++ if (start_size > max_size || start_size < 1)+ return NULL;++ stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);+ if (stack == NULL)+ return NULL;++ /* Align max_size. */+ page_align = get_page_alignment();+ max_size = (max_size + page_align) & ~page_align;++#ifdef _WIN32+ ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE);+ if (!ptr) {+ SLJIT_FREE(stack, allocator_data);+ return NULL;+ }++ stack->min_start = (sljit_u8 *)ptr;+ stack->end = stack->min_start + max_size;+ stack->start = stack->end;++ if (sljit_stack_resize(stack, stack->end - start_size) == NULL) {+ sljit_free_stack(stack, allocator_data);+ return NULL;+ }+#else /* !_WIN32 */+#ifdef MAP_ANON+ ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);+#else /* !MAP_ANON */+ if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) {+ SLJIT_FREE(stack, allocator_data);+ return NULL;+ }+ ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);+#endif /* MAP_ANON */+ if (ptr == MAP_FAILED) {+ SLJIT_FREE(stack, allocator_data);+ return NULL;+ }+ stack->min_start = (sljit_u8 *)ptr;+ stack->end = stack->min_start + max_size;+ stack->start = stack->end - start_size;+#endif /* _WIN32 */++ stack->top = stack->end;+ return stack;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)+{+#if defined _WIN32 || defined(POSIX_MADV_DONTNEED)+ sljit_uw aligned_old_start;+ sljit_uw aligned_new_start;+ sljit_sw page_align;+#endif++ if ((new_start < stack->min_start) || (new_start >= stack->end))+ return NULL;++#ifdef _WIN32+ page_align = get_page_alignment();++ aligned_new_start = (sljit_uw)new_start & ~page_align;+ aligned_old_start = ((sljit_uw)stack->start) & ~page_align;+ if (aligned_new_start != aligned_old_start) {+ if (aligned_new_start < aligned_old_start) {+ if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE))+ return NULL;+ }+ else {+ if (!VirtualFree((void*)aligned_old_start, aligned_new_start - aligned_old_start, MEM_DECOMMIT))+ return NULL;+ }+ }+#elif defined(POSIX_MADV_DONTNEED)+ if (stack->start < new_start) {+ page_align = get_page_alignment();++ aligned_new_start = (sljit_uw)new_start & ~page_align;+ aligned_old_start = ((sljit_uw)stack->start) & ~page_align;++ if (aligned_new_start > aligned_old_start) {+ posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED);+#ifdef MADV_FREE+ madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_FREE);+#endif /* MADV_FREE */+ }+ }+#endif /* _WIN32 */++ stack->start = new_start;+ return new_start;+}++#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */++#endif /* SLJIT_UTIL_STACK */
+ src/c/pcre2/src/sljit/sljitWXExecAllocator.c view
@@ -0,0 +1,225 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without modification, are+ * permitted provided that the following conditions are met:+ *+ * 1. Redistributions of source code must retain the above copyright notice, this list of+ * conditions and the following disclaimer.+ *+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.+ */++/*+ This file contains a simple W^X executable memory allocator for POSIX+ like systems and Windows++ In *NIX, MAP_ANON is required (that is considered a feature) so make+ sure to set the right availability macros for your system or the code+ will fail to build.++ If your system doesn't support mapping of anonymous pages (ex: IRIX) it+ is also likely that it doesn't need this allocator and should be using+ the standard one instead.++ It allocates a separate map for each code block and may waste a lot of+ memory, because whatever was requested, will be rounded up to the page+ size (minimum 4KB, but could be even bigger).++ It changes the page permissions (RW <-> RX) as needed and therefore, if you+ will be updating the code after it has been generated, need to make sure to+ block any concurrent execution, or could result in a SIGBUS, that could+ even manifest itself at a different address than the one that was being+ modified.++ Only use if you are unable to use the regular allocator because of security+ restrictions and adding exceptions to your application or the system are+ not possible.+*/++#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \+ sljit_update_wx_flags((from), (to), (enable_exec))++#ifndef _WIN32+#include <sys/types.h>+#include <sys/mman.h>++#ifdef __NetBSD__+#if defined(PROT_MPROTECT)+#define check_se_protected(ptr, size) (0)+#define SLJIT_PROT_WX PROT_MPROTECT(PROT_EXEC)+#else /* !PROT_MPROTECT */+#ifdef _NETBSD_SOURCE+#include <sys/param.h>+#else /* !_NETBSD_SOURCE */+typedef unsigned int u_int;+#define devmajor_t sljit_s32+#endif /* _NETBSD_SOURCE */+#include <sys/sysctl.h>+#include <unistd.h>++#define check_se_protected(ptr, size) netbsd_se_protected()++static SLJIT_INLINE int netbsd_se_protected(void)+{+ int mib[3];+ int paxflags;+ size_t len = sizeof(paxflags);++ mib[0] = CTL_PROC;+ mib[1] = getpid();+ mib[2] = PROC_PID_PAXFLAGS;++ if (SLJIT_UNLIKELY(sysctl(mib, 3, &paxflags, &len, NULL, 0) < 0))+ return -1;++ return (paxflags & CTL_PROC_PAXFLAGS_MPROTECT) ? -1 : 0;+}+#endif /* PROT_MPROTECT */+#else /* POSIX */+#define check_se_protected(ptr, size) generic_se_protected(ptr, size)++static SLJIT_INLINE int generic_se_protected(void *ptr, sljit_uw size)+{+ if (SLJIT_LIKELY(!mprotect(ptr, size, PROT_EXEC)))+ return mprotect(ptr, size, PROT_READ | PROT_WRITE);++ return -1;+}+#endif /* NetBSD */++#if defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED+#define SLJIT_SE_LOCK()+#define SLJIT_SE_UNLOCK()+#else /* !SLJIT_SINGLE_THREADED */+#include <pthread.h>+#define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock)+#define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock)+#endif /* SLJIT_SINGLE_THREADED */++#ifndef SLJIT_PROT_WX+#define SLJIT_PROT_WX 0+#endif /* !SLJIT_PROT_WX */++SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)+{+#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)+ static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER;+#endif+ static int se_protected = !SLJIT_PROT_WX;+ sljit_uw* ptr;++ if (SLJIT_UNLIKELY(se_protected < 0))+ return NULL;++ size += sizeof(sljit_uw);+ ptr = (sljit_uw*)mmap(NULL, size, PROT_READ | PROT_WRITE | SLJIT_PROT_WX,+ MAP_PRIVATE | MAP_ANON, -1, 0);++ if (ptr == MAP_FAILED)+ return NULL;++ if (SLJIT_UNLIKELY(se_protected > 0)) {+ SLJIT_SE_LOCK();+ se_protected = check_se_protected(ptr, size);+ SLJIT_SE_UNLOCK();+ if (SLJIT_UNLIKELY(se_protected < 0)) {+ munmap((void *)ptr, size);+ return NULL;+ }+ }++ *ptr++ = size;+ return ptr;+}++#undef SLJIT_PROT_WX+#undef SLJIT_SE_UNLOCK+#undef SLJIT_SE_LOCK++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)+{+ sljit_uw *start_ptr = ((sljit_uw*)ptr) - 1;+ munmap((void*)start_ptr, *start_ptr);+}++static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)+{+ sljit_uw page_mask = (sljit_uw)get_page_alignment();+ sljit_uw start = (sljit_uw)from;+ sljit_uw end = (sljit_uw)to;+ int prot = PROT_READ | (enable_exec ? PROT_EXEC : PROT_WRITE);++ SLJIT_ASSERT(start < end);++ start &= ~page_mask;+ end = (end + page_mask) & ~page_mask;++ mprotect((void*)start, end - start, prot);+}++#else /* windows */++SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)+{+ sljit_uw *ptr;++ size += sizeof(sljit_uw);+ ptr = (sljit_uw*)VirtualAlloc(NULL, size,+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);++ if (!ptr)+ return NULL;++ *ptr++ = size;++ return ptr;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)+{+ sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw);+#if defined(SLJIT_DEBUG) && SLJIT_DEBUG+ sljit_uw page_mask = (sljit_uw)get_page_alignment();++ SLJIT_ASSERT(!(start & page_mask));+#endif+ VirtualFree((void*)start, 0, MEM_RELEASE);+}++static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)+{+ DWORD oldprot;+ sljit_uw page_mask = (sljit_uw)get_page_alignment();+ sljit_uw start = (sljit_uw)from;+ sljit_uw end = (sljit_uw)to;+ DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE;++ SLJIT_ASSERT(start < end);++ start &= ~page_mask;+ end = (end + page_mask) & ~page_mask;++ VirtualProtect((void*)start, end - start, prot, &oldprot);+}++#endif /* !windows */++SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)+{+ /* This allocator does not keep unused memory for future allocations. */+}
+ src/c/pcre2_chartables.c view
@@ -0,0 +1,204 @@+// Copied per the PCRE2 source's NON-AUTOTOOLS-BUILD instructions.++/*************************************************+* Perl-Compatible Regular Expressions *+*************************************************/++/* This file was automatically written by the pcre2_dftables auxiliary+program. It contains character tables that are used when no external+tables are passed to PCRE2 by the application that calls it. The tables+are used only for characters whose code values are less than 256. */++/* This set of tables was written in the C locale. */++/* The pcre2_ftables program (which is distributed with PCRE2) can be used+to build alternative versions of this file. This is necessary if you are+running in an EBCDIC environment, or if you want to default to a different+encoding, for example ISO-8859-1. When pcre2_dftables is run, it creates+these tables in the "C" locale by default. This happens automatically if+PCRE2 is configured with --enable-rebuild-chartables. However, you can run+pcre2_dftables manually with the -L option to build tables using the LC_ALL+locale. */++/* The following #include is present because without it gcc 4.x may remove+the array definition from the final binary if PCRE2 is built into a static+library and dead code stripping is activated. This leads to link errors.+Pulling in the header ensures that the array gets flagged as "someone+outside this compilation unit might reference this" and so it will always+be supplied to the linker. */++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++#include "pcre2_internal.h"++const uint8_t PRIV(default_tables)[] = {++/* This table is a lower casing table. */++ 0, 1, 2, 3, 4, 5, 6, 7,+ 8, 9, 10, 11, 12, 13, 14, 15,+ 16, 17, 18, 19, 20, 21, 22, 23,+ 24, 25, 26, 27, 28, 29, 30, 31,+ 32, 33, 34, 35, 36, 37, 38, 39,+ 40, 41, 42, 43, 44, 45, 46, 47,+ 48, 49, 50, 51, 52, 53, 54, 55,+ 56, 57, 58, 59, 60, 61, 62, 63,+ 64, 97, 98, 99,100,101,102,103,+ 104,105,106,107,108,109,110,111,+ 112,113,114,115,116,117,118,119,+ 120,121,122, 91, 92, 93, 94, 95,+ 96, 97, 98, 99,100,101,102,103,+ 104,105,106,107,108,109,110,111,+ 112,113,114,115,116,117,118,119,+ 120,121,122,123,124,125,126,127,+ 128,129,130,131,132,133,134,135,+ 136,137,138,139,140,141,142,143,+ 144,145,146,147,148,149,150,151,+ 152,153,154,155,156,157,158,159,+ 160,161,162,163,164,165,166,167,+ 168,169,170,171,172,173,174,175,+ 176,177,178,179,180,181,182,183,+ 184,185,186,187,188,189,190,191,+ 192,193,194,195,196,197,198,199,+ 200,201,202,203,204,205,206,207,+ 208,209,210,211,212,213,214,215,+ 216,217,218,219,220,221,222,223,+ 224,225,226,227,228,229,230,231,+ 232,233,234,235,236,237,238,239,+ 240,241,242,243,244,245,246,247,+ 248,249,250,251,252,253,254,255,++/* This table is a case flipping table. */++ 0, 1, 2, 3, 4, 5, 6, 7,+ 8, 9, 10, 11, 12, 13, 14, 15,+ 16, 17, 18, 19, 20, 21, 22, 23,+ 24, 25, 26, 27, 28, 29, 30, 31,+ 32, 33, 34, 35, 36, 37, 38, 39,+ 40, 41, 42, 43, 44, 45, 46, 47,+ 48, 49, 50, 51, 52, 53, 54, 55,+ 56, 57, 58, 59, 60, 61, 62, 63,+ 64, 97, 98, 99,100,101,102,103,+ 104,105,106,107,108,109,110,111,+ 112,113,114,115,116,117,118,119,+ 120,121,122, 91, 92, 93, 94, 95,+ 96, 65, 66, 67, 68, 69, 70, 71,+ 72, 73, 74, 75, 76, 77, 78, 79,+ 80, 81, 82, 83, 84, 85, 86, 87,+ 88, 89, 90,123,124,125,126,127,+ 128,129,130,131,132,133,134,135,+ 136,137,138,139,140,141,142,143,+ 144,145,146,147,148,149,150,151,+ 152,153,154,155,156,157,158,159,+ 160,161,162,163,164,165,166,167,+ 168,169,170,171,172,173,174,175,+ 176,177,178,179,180,181,182,183,+ 184,185,186,187,188,189,190,191,+ 192,193,194,195,196,197,198,199,+ 200,201,202,203,204,205,206,207,+ 208,209,210,211,212,213,214,215,+ 216,217,218,219,220,221,222,223,+ 224,225,226,227,228,229,230,231,+ 232,233,234,235,236,237,238,239,+ 240,241,242,243,244,245,246,247,+ 248,249,250,251,252,253,254,255,++/* This table contains bit maps for various character classes. Each map is 32+bytes long and the bits run from the least significant end of each byte. The+classes that have their own maps are: space, xdigit, digit, upper, lower, word,+graph, print, punct, and cntrl. Other classes are built from combinations. */++ 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, /* space */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, /* xdigit */+ 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, /* digit */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* upper */+ 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* lower */+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, /* word */+ 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, /* graph */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, /* print */+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, /* punct */+ 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, /* cntrl */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++/* This table identifies various classes of character by individual bits:+ 0x01 white space character+ 0x02 letter+ 0x04 lower case letter+ 0x08 decimal digit+ 0x10 alphanumeric or '_'+*/++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */+ 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */+ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0 - 7 */+ 0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */+ 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* @ - G */+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */+ 0x12,0x12,0x12,0x00,0x00,0x00,0x00,0x10, /* X - _ */+ 0x00,0x16,0x16,0x16,0x16,0x16,0x16,0x16, /* ` - g */+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, /* h - o */+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, /* p - w */+ 0x16,0x16,0x16,0x00,0x00,0x00,0x00,0x00, /* x -127 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */++/* End of pcre2_chartables.c */
+ src/hs/Text/Regex/Pcre2.hs view
@@ -0,0 +1,354 @@+module Text.Regex.Pcre2 (+ -- * Matching and substitution+ {-|+ /__Introduction__/++ Atop the low-level binding to the C API, we present a high-level interface+ to add regular expressions to Haskell programs.++ All input and output strings are strict `Text`, which maps directly to how+ PCRE2 operates on strings of 16-bit-wide code units.++ The C API requires pattern strings to be compiled and the compiled patterns+ to be executed on subject strings in discrete steps. We hide this+ procedure, accepting pattern and subject as arguments in a single function,+ essentially:++ > pattern -> subject -> result++ The implementation guarantees that,+ when [partially applied](https://wiki.haskell.org/Partial_application) to+ pattern but not subject, the resulting function+ will [close](https://en.wikipedia.org/wiki/Closure_(computer_programming\))+ on the underlying compiled object and reuse it for every subject it is+ subsequently applied to.++ Likewise, we do not require the user to know whether a PCRE2 option is to be+ applied at pattern compile time or match time. Instead we fold all possible+ options into a single datatype, `Option`. Most functions have vanilla and+ configurable variants; the latter have \"@Opt@\" in the name and accept a+ value of this type.++ Similar to how @head :: [a] -> a@ sacrifices totality for type simplicity,+ we represent user errors as imprecise exceptions. Unlike with @head@, these+ exceptions are typed (as `SomePcre2Exception`s); moreover, we offer Template+ Haskell facilities that can intercept some of these errors before the+ program is run. (Failure to match is not considered a user error and is+ represented in the types.)++ [There's more than one way to do it](https://en.wikipedia.org/wiki/There's_more_than_one_way_to_do_it)+ with this library. The choices between functions and traversals,+ poly-kinded `Captures` and plain lists, string literals and+ quasi-quotations, quasi-quoted expressions and quasi-quoted patterns...these+ are left to the user. She will observe that advanced features\' extra+ safety, power, and convenience entail additional language extensions,+ cognitive overhead, and (for lenses) library dependencies, so it\'s really a+ matter of finding the best trade-offs for her case.++ /__Definitions__/++ [Pattern]: The string defining a regular expression. Refer to+ syntax [here](https://pcre.org/current/doc/html/pcre2pattern.html).++ [Subject]: The string the compiled regular expression is executed on.++ [Regex]: A function of the form @`Text` -> result@, where the argument is+ the subject. It is \"compiled\" via partial application as discussed above.+ (Lens users: A regex has the more abstract form+ @[Traversal\'](https://hackage.haskell.org/package/microlens/docs/Lens-Micro.html#t:Traversal-39-)+ `Text` result@, but the concept is the same.)++ [Capture (or capture group)]: Any substrings of the subject matched by the+ pattern, meaning the whole pattern and any parenthesized groupings. The+ PCRE2 docs do not refer to the former as a \"capture\"; however it is+ accessed the same way in the C API, just with index 0, so we will consider+ it the 0th capture for consistency. Parenthesized captures are implicitly+ numbered from 1.++ [Unset capture]: A capture considered unset as distinct from empty. This+ can arise from matching the pattern @(a)?@ to an empty subject—the+ 0th capture will be set as empty, but the 1st will be unset altogether. We+ represent both as empty `Text` for simplicity. See below for discussions+ about how unset captures may be detected or substituted using this library.++ [Named capture]: A parenthesized capture can be named like this:+ @(?\<foo\>...)@. Whether they have names or not, captures are always+ numbered as described above.++ /__Performance__/++ Each API function is designed such that, when a regex is obtained, the+ underlying C data generated from the pattern and any options is reused for+ that regex\'s lifetime. Care should be taken that the same regex is not+ recreated /ex nihilo/ and discarded for each new subject:++ > isEmptyOrHas2Digits :: Text -> Bool+ > isEmptyOrHas2Digits s = Text.null s || matches "\\d{2}" s -- bad, fully applied++ Instead, store it in a partially applied state:++ > isEmptyOrHas2Digits = (||) <$> Text.null <*> matches "\\d{2}" -- OK but abstruse++ When in doubt, always create regexes as top-level values:++ > has2Digits :: Text -> Bool+ > has2Digits = matches "\\d{2}"+ >+ > isEmptyOrHas2Digits s = Text.null s || has2Digits s -- good++ Note: Template Haskell regexes are immune from this problem and may be+ freely inlined; see below.++ /__Handling errors__/++ In a few places we use the `Alternative` typeclass to optionally return+ match results, expressing success via `pure` and failure via `empty`.+ Typically the user will choose the instance `Maybe`, but other useful ones+ exist, notably @[STM](https://hackage.haskell.org/package/stm/docs/Control-Monad-STM.html#t:STM)@,+ that of [optparse-applicative](https://hackage.haskell.org/package/optparse-applicative/docs/Options-Applicative.html#t:Parser),+ and those of parser combinator libraries such+ as [megaparsec](https://hackage.haskell.org/package/megaparsec/docs/Text-Megaparsec.html#t:ParsecT).++ By contrast, user errors are thrown purely. If a user error is to be+ caught, it must be at the site where the match or substitution results are+ evaluated—in other words, wherever the regex is applied to a subject.+ Even pattern compile errors are deferred to match sites, due to the way this+ library employs `System.IO.Unsafe.unsafePerformIO` to implement laziness.++ >>> broken = match "*"+ >>> broken "foo"+ *** Exception: pcre2_compile: quantifier does not follow a repeatable item+ *+ ^++ `Control.Exception.evaluate` comes in handy to force results into the `IO`+ monad in order to catch errors reliably:++ >>> evaluate (broken "foo") `catch` \(_ :: SomePcre2Exception) -> return Nothing+ Nothing++ Or simply select `IO` as the `Alternative` instance:++ >>> :t broken+ broken :: Alternative f => Text -> f Text+ >>> broken "foo" `catch` \(_ :: SomePcre2Exception) -> return "broken"+ "broken"+ -}++ -- ** Basic matching functions+ match,+ matchOpt,+ matches,+ matchesOpt,+ captures,+ capturesOpt,+ capturesA,+ capturesOptA,++ -- ** PCRE2-native substitution+ sub,+ gsub,+ subOpt,++ -- ** Lens-powered matching and substitution+ --+ -- | To use this portion of the library, there are two prerequisites:+ --+ -- 1. A basic working understanding of optics. Many tutorials exist+ -- online, such as+ -- [this](https://hackage.haskell.org/package/lens-tutorial-1.0.4/docs/Control-Lens-Tutorial.html),+ -- and videos such as [this](https://www.youtube.com/watch?v=7fbziKgQjnw).+ --+ -- 2. A library providing combinators. For lens newcomers, it is+ -- recommended to grab+ -- [microlens-platform](https://hackage.haskell.org/package/microlens-platform)—most+ -- of the examples in this library work with it,+ -- @[packed](https://hackage.haskell.org/package/microlens-platform/docs/Lens-Micro-Platform.html#v:packed)@+ -- and+ -- @[unpacked](https://hackage.haskell.org/package/microlens-platform/docs/Lens-Micro-Platform.html#v:packed)@+ -- are included for working with `Text`, and it is upwards-compatible with+ -- the full [lens](https://hackage.haskell.org/package/lens) library.+ --+ -- We expose a set of traversals that focus on matched substrings within a+ -- subject. Like the basic functional regexes, they should be \"compiled\"+ -- and memoized, rather than created inline.+ --+ -- > _nee :: Traversal' Text Text+ -- > _nee = _match "(?i)\\bnee\\b"+ --+ -- In addition to getting results, they support substitution through+ -- setting; more generally, they can accrete effects while performing+ -- replacements.+ --+ -- >>> promptNee = traverseOf (_nee . unpacked) $ \s -> print s >> getLine+ -- >>> promptNee "We are the knights who say...NEE!"+ -- "NEE"+ -- NOO+ -- "We are the knights who say...NOO!"+ -- >>>+ --+ -- The optic interface signals match failure by not targeting anything.+ --+ -- >>> promptNee "Shhhhh"+ -- "Shhhhh"+ -- >>>+ --+ -- In general these traversals are not law-abiding.+ _match,+ _matchOpt,+ _captures,+ _capturesOpt,++ -- * Compile-time validation+ --+ -- | Despite whatever virtues, the API thus far has some fragility arising+ -- from various scenarios:+ --+ -- * pattern malformation such as mismatched parentheses /(runtime error)/+ --+ -- * out-of-bounds indexing of a capture group list /(runtime error)/+ --+ -- * out-of-bounds @ix@ing of a @Traversal\'@ target+ -- /(spurious failure to match)/+ --+ -- * case expression containing a Haskell list pattern of the wrong length+ -- /(spurious failure to match)/+ --+ -- * regex created and discarded inline /(suboptimal performance)/+ --+ -- * precariously many backslashes in a pattern. Matching a literal+ -- backslash requires the sequence @\"\\\\\\\\\"@!+ --+ -- Using a combination of language extensions and pattern introspection+ -- features, we provide a Template Haskell API to mitigate these scenarios.+ -- To make use of it these must be enabled:+ --+ -- +--------------------+---------------------------------------+------------------------------++ -- | Extension | Required for | When |+ -- +====================+=======================================+==============================++ -- | @DataKinds@ | `GHC.TypeLits.Nat`s (numbers), | Using `regex`\/`_regex` with |+ -- | | `GHC.TypeLits.Symbol`s (strings), and | a pattern containing |+ -- | | other type-level data powering | parenthesized captures |+ -- | | compile-time capture lookups | |+ -- +--------------------+---------------------------------------+------------------------------++ -- | @QuasiQuotes@ | @[@/f/@|@...@|]@ syntax | Always |+ -- +--------------------+---------------------------------------+------------------------------++ -- | @TemplateHaskell@ | Running PCRE2 at compile time and | Always |+ -- | | generating code | |+ -- +--------------------+---------------------------------------+------------------------------++ -- | @TypeApplications@ | @\@i@ syntax for supplying type index | Using `capture`\/`_capture` |+ -- | | arguments to applicable functions | |+ -- +--------------------+---------------------------------------+------------------------------++ -- | @ViewPatterns@ | Running code and binding variables in | Using `regex` as a Haskell |+ -- | | pattern context proper (pattern | pattern |+ -- | | guards are off-limits for this) | |+ -- +--------------------+---------------------------------------+------------------------------++ --+ -- The inspiration for this portion of the library is Ruby, which supports+ -- regular expressions with [superior ergonomics](https://ruby-doc.org/core-2.7.2/Regexp.html#class-Regexp-label-Capturing).++ -- ** Quasi-quoters+ regex,+ _regex,++ -- ** Type-indexed capture groups+ Captures(),+ capture,+ _capture,++ -- * Options++ Option(+ AllowEmptyClass,+ AltBsux,+ AltBsuxLegacy,+ AltCircumflex,+ AltVerbNames,+ Anchored,+ AutoCallout,+ BadEscapeIsLiteral,+ Bsr,+ Caseless,+ DepthLimit,+ DollarEndOnly,+ DotAll,+ DupNames,+ EndAnchored,+ EscapedCrIsLf,+ Extended,+ ExtendedMore,+ FirstLine,+ HeapLimit,+ Literal,+ MatchLimit,+ MatchLine,+ MatchUnsetBackRef,+ MatchWord,+ MaxPatternLength,+ Multiline,+ NeverBackslashC,+ NeverUcp,+ Newline,+ NoAutoCapture,+ NoAutoPossess,+ NoDotStarAnchor,+ NoStartOptimize,+ NotBol,+ NotEmpty,+ NotEmptyAtStart,+ NotEol,+ OffsetLimit,+ ParensLimit,+ PartialHard,+ PartialSoft,+ SubGlobal,+ SubLiteral,+ SubReplacementOnly,+ SubUnknownUnset,+ SubUnsetEmpty,+ Ucp,+ Ungreedy,+ UnsafeCallout,+ UnsafeCompileRecGuard,+ UnsafeSubCallout,+ Utf),++ Bsr(..),+ Newline(..),++ -- ** Callout interface+ -- *** Capture callouts+ CalloutInfo(..),+ CalloutIndex(..),+ CalloutResult(..),+ -- *** Substitution callouts+ SubCalloutInfo(..),+ SubCalloutResult(..),++ -- * User errors+ SomePcre2Exception(),+ Pcre2Exception(),+ Pcre2CompileException(),++ -- * PCRE2 build configuration+ defaultBsr,+ compiledWidths,+ defaultDepthLimit,+ defaultHeapLimit,+ supportsJit,+ jitTarget,+ linkSize,+ defaultMatchLimit,+ defaultNewline,+ defaultIsNeverBackslashC,+ defaultParensLimit,+ defaultTablesLength,+ unicodeVersion,+ supportsUnicode,+ pcreVersion)+where++import Control.Applicative (Alternative(..))+import Data.Text (Text)+import Text.Regex.Pcre2.Internal+import Text.Regex.Pcre2.TH
+ src/hs/Text/Regex/Pcre2/Foreign.hs view
@@ -0,0 +1,639 @@+{-# LANGUAGE CApiFFI #-}+{-# LANGUAGE TemplateHaskell #-}++-- | A complete binding to the low-level C API.+--+-- Items here are named identically to their C counterparts. Therefore,+-- documentation will be sparse;+-- [the official PCRE2 API docs](https://pcre.org/current/doc/html/pcre2api.html#SEC36)+-- should suffice.+module Text.Regex.Pcre2.Foreign where++import Foreign+import Foreign.C.Types+import Text.Regex.Pcre2.Foreign.TH (constant, getter)++-- * Types++-- | \"The @UCHAR@ types define unsigned code units of the appropriate widths.+-- For example, @PCRE2_UCHAR16@ is usually defined as @uint16_t@.\"+type PCRE2_UCHAR = CUShort++-- | \"The @SPTR@ types are constant pointers to the equivalent @UCHAR@ types,+-- that is, they are pointers to vectors of unsigned code units.\"+type PCRE2_SPTR = Ptr PCRE2_UCHAR++-- | \"...string lengths and offsets into strings of code units...are always of+-- type @PCRE2_SIZE@...currently always defined as @size_t@.\"+type PCRE2_SIZE = CSize++-- ** Opaque types+--+-- $OpaqueTypes+-- These correspond to structs that are only ever passed by reference. They+-- simply exist for type safety and cannot be constructed in Haskell.+data Pcre2_general_context+data Pcre2_compile_context+data Pcre2_match_context+data Pcre2_callout_block+data Pcre2_substitute_callout_block+data Pcre2_code+data Pcre2_jit_stack+data Pcre2_match_data+data Pcre2_callout_enumerate_block++-- * The general context++foreign import capi safe "pcre2.h" pcre2_general_context_create+ :: FunPtr (PCRE2_SIZE -> Ptr a -> IO (Ptr b)) -- ^ custom malloc+ -> FunPtr (Ptr b -> Ptr a -> IO ()) -- ^ custom free+ -> Ptr a+ -> IO (Ptr Pcre2_general_context)++foreign import capi safe "pcre2.h" pcre2_general_context_copy+ :: Ptr Pcre2_general_context+ -> IO (Ptr Pcre2_general_context)++foreign import capi safe "pcre2.h" pcre2_general_context_free+ :: Ptr Pcre2_general_context+ -> IO ()++-- * The compile context++foreign import capi safe "pcre2.h" pcre2_compile_context_create+ :: Ptr Pcre2_general_context+ -> IO (Ptr Pcre2_compile_context)++foreign import capi safe "pcre2.h" pcre2_compile_context_copy+ :: Ptr Pcre2_compile_context+ -> IO (Ptr Pcre2_compile_context)++foreign import capi safe "pcre2.h" pcre2_compile_context_free+ :: Ptr Pcre2_compile_context+ -> IO ()++-- ** Compile context setters++-- TODO Maybe this goes next to wherever errors appear in the docs?+constant "ERROR_BADDATA" ''CInt++foreign import capi unsafe "pcre2.h" pcre2_set_bsr+ :: Ptr Pcre2_compile_context+ -> CUInt -- ^ See below for possible values.+ -> IO CInt++constant "BSR_ANYCRLF" ''CUInt+constant "BSR_UNICODE" ''CUInt++foreign import capi "pcre2.h" pcre2_set_character_tables+ :: Ptr Pcre2_compile_context+ -> Ptr CUChar+ -> IO CInt++foreign import capi unsafe "pcre2.h" pcre2_set_compile_extra_options+ :: Ptr Pcre2_compile_context+ -> CUInt -- ^ See \"Extra compile options\" below for possible bit flags.+ -> IO CInt++foreign import capi unsafe "pcre2.h" pcre2_set_max_pattern_length+ :: Ptr Pcre2_compile_context+ -> PCRE2_SIZE+ -> IO CInt++foreign import capi unsafe "pcre2.h" pcre2_set_newline+ :: Ptr Pcre2_compile_context+ -> CUInt -- ^ See below for possible values.+ -> IO CInt++constant "NEWLINE_CR" ''CUInt+constant "NEWLINE_LF" ''CUInt+constant "NEWLINE_CRLF" ''CUInt+constant "NEWLINE_ANY" ''CUInt+constant "NEWLINE_ANYCRLF" ''CUInt+constant "NEWLINE_NUL" ''CUInt++foreign import capi unsafe "pcre2.h" pcre2_set_parens_nest_limit+ :: Ptr Pcre2_compile_context+ -> CUInt+ -> IO CInt++foreign import capi unsafe "pcre2.h" pcre2_set_compile_recursion_guard+ :: Ptr Pcre2_compile_context+ -> FunPtr (CUInt -> Ptr a -> IO CInt)+ -> Ptr a+ -> IO CInt++-- * The match context++foreign import capi safe "pcre2.h" pcre2_match_context_create+ :: Ptr Pcre2_general_context+ -> IO (Ptr Pcre2_match_context)++foreign import capi safe "pcre2.h" pcre2_match_context_copy+ :: Ptr Pcre2_match_context+ -> IO (Ptr Pcre2_match_context)++foreign import capi safe "pcre2.h" pcre2_match_context_free+ :: Ptr Pcre2_match_context+ -> IO ()++-- ** Match context setters++foreign import capi unsafe "pcre2.h" pcre2_set_callout+ :: Ptr Pcre2_match_context+ -> FunPtr (Ptr Pcre2_callout_block -> Ptr a -> IO CInt)+ -> Ptr a+ -> IO CInt++foreign import capi unsafe "pcre2.h" pcre2_set_substitute_callout+ :: Ptr Pcre2_match_context+ -> FunPtr (Ptr Pcre2_substitute_callout_block -> Ptr a -> IO CInt)+ -> Ptr a+ -> IO CInt++foreign import capi unsafe "pcre2.h" pcre2_set_offset_limit+ :: Ptr Pcre2_match_context+ -> PCRE2_SIZE -- ^ Can be unset. See below.+ -> IO CInt++constant "UNSET" ''PCRE2_SIZE++foreign import capi unsafe "pcre2.h" pcre2_set_heap_limit+ :: Ptr Pcre2_match_context+ -> CUInt+ -> IO CInt++foreign import capi unsafe "pcre2.h" pcre2_set_match_limit+ :: Ptr Pcre2_match_context+ -> CUInt+ -> IO CInt++foreign import capi unsafe "pcre2.h" pcre2_set_depth_limit+ :: Ptr Pcre2_match_context+ -> CUInt+ -> IO CInt++-- * Checking build-time options++foreign import capi unsafe "pcre2.h" pcre2_config+ :: CUInt -- ^ See below for possible values.+ -> Ptr a -- ^ See the C API docs for what gets returned here.+ -> IO CInt++constant "CONFIG_BSR" ''CUInt+constant "CONFIG_COMPILED_WIDTHS" ''CUInt+constant "CONFIG_DEPTHLIMIT" ''CUInt+constant "CONFIG_HEAPLIMIT" ''CUInt+constant "CONFIG_JIT" ''CUInt+constant "CONFIG_JITTARGET" ''CUInt+constant "CONFIG_LINKSIZE" ''CUInt+constant "CONFIG_MATCHLIMIT" ''CUInt+constant "CONFIG_NEWLINE" ''CUInt+constant "CONFIG_NEVER_BACKSLASH_C" ''CUInt+constant "CONFIG_PARENSLIMIT" ''CUInt+constant "CONFIG_STACKRECURSE" ''CUInt+constant "CONFIG_TABLES_LENGTH" ''CUInt+constant "CONFIG_UNICODE_VERSION" ''CUInt+constant "CONFIG_UNICODE" ''CUInt+constant "CONFIG_VERSION" ''CUInt++-- * Compiling a pattern++foreign import capi safe "pcre2.h" pcre2_compile+ :: PCRE2_SPTR+ -> PCRE2_SIZE -- ^ Can be zero-terminated. See below.+ -> CUInt+ -- ^ See \"Main compile options\" below for possible bit flags.+ -> Ptr CInt+ -> Ptr PCRE2_SIZE+ -> Ptr Pcre2_compile_context+ -> IO (Ptr Pcre2_code)++constant "ZERO_TERMINATED" ''PCRE2_SIZE++foreign import capi safe "pcre2.h" pcre2_code_free+ :: Ptr Pcre2_code+ -> IO ()++foreign import capi safe "pcre2.h" pcre2_code_copy+ :: Ptr Pcre2_code+ -> IO (Ptr Pcre2_code)++foreign import capi "pcre2.h" pcre2_code_copy_with_tables+ :: Ptr Pcre2_code+ -> IO (Ptr Pcre2_code)++-- ** Main compile options+constant "ANCHORED" ''CUInt+constant "ALLOW_EMPTY_CLASS" ''CUInt+constant "ALT_BSUX" ''CUInt+constant "ALT_CIRCUMFLEX" ''CUInt+constant "ALT_VERBNAMES" ''CUInt+constant "AUTO_CALLOUT" ''CUInt+constant "CASELESS" ''CUInt+constant "DOLLAR_ENDONLY" ''CUInt+constant "DOTALL" ''CUInt+constant "DUPNAMES" ''CUInt+constant "ENDANCHORED" ''CUInt+constant "EXTENDED" ''CUInt+constant "EXTENDED_MORE" ''CUInt+constant "FIRSTLINE" ''CUInt+constant "LITERAL" ''CUInt+constant "MATCH_INVALID_UTF" ''CUInt+constant "MATCH_UNSET_BACKREF" ''CUInt+constant "MULTILINE" ''CUInt+constant "NEVER_BACKSLASH_C" ''CUInt+constant "NEVER_UCP" ''CUInt+constant "NEVER_UTF" ''CUInt+constant "NO_AUTO_CAPTURE" ''CUInt+constant "NO_AUTO_POSSESS" ''CUInt+constant "NO_DOTSTAR_ANCHOR" ''CUInt+constant "NO_START_OPTIMIZE" ''CUInt+constant "NO_UTF_CHECK" ''CUInt+constant "UCP" ''CUInt+constant "UNGREEDY" ''CUInt+constant "USE_OFFSET_LIMIT" ''CUInt+constant "UTF" ''CUInt++-- ** Extra compile options+constant "EXTRA_ALLOW_SURROGATE_ESCAPES" ''CUInt+constant "EXTRA_ALT_BSUX" ''CUInt+constant "EXTRA_BAD_ESCAPE_IS_LITERAL" ''CUInt+constant "EXTRA_ESCAPED_CR_IS_LF" ''CUInt+constant "EXTRA_MATCH_LINE" ''CUInt+constant "EXTRA_MATCH_WORD" ''CUInt++-- * JIT compilation++foreign import capi safe "pcre2.h" pcre2_jit_compile+ :: Ptr Pcre2_code+ -> CUInt -- ^ See below for possible bit flags.+ -> IO CInt++constant "JIT_COMPLETE" ''CUInt+constant "JIT_PARTIAL_HARD" ''CUInt+constant "JIT_PARTIAL_SOFT" ''CUInt++-- | May be returned by 'pcre2_jit_compile'.+constant "ERROR_JIT_BADOPTION" ''CInt++foreign import capi safe "pcre2.h" pcre2_jit_match+ :: Ptr Pcre2_code+ -> PCRE2_SPTR -- ^ subject+ -> PCRE2_SIZE -- ^ length+ -> PCRE2_SIZE -- ^ startoffset+ -> CUInt -- ^ options+ -> Ptr Pcre2_match_data+ -> Ptr Pcre2_match_context+ -> IO CInt++foreign import capi safe "pcre2.h" pcre2_jit_free_unused_memory+ :: Ptr Pcre2_general_context+ -> IO ()++foreign import capi safe "pcre2.h" pcre2_jit_stack_create+ :: PCRE2_SIZE+ -> PCRE2_SIZE+ -> Ptr Pcre2_general_context+ -> IO (Ptr Pcre2_jit_stack)++foreign import capi unsafe "pcre2.h" pcre2_jit_stack_assign+ :: Ptr Pcre2_match_context+ -> FunPtr (Ptr a -> IO (Ptr Pcre2_jit_stack))+ -> Ptr a+ -> IO ()++foreign import capi safe "pcre2.h" pcre2_jit_stack_free+ :: Ptr Pcre2_jit_stack+ -> IO ()++-- * Locale support++foreign import capi safe "pcre2.h" pcre2_maketables+ :: Ptr Pcre2_general_context+ -> IO (Ptr CUChar)++foreign import capi safe "pcre2.h" pcre2_maketables_free+ :: Ptr Pcre2_general_context+ -> Ptr CUChar+ -> IO ()++-- * Information about a compiled pattern++foreign import capi unsafe "pcre2.h" pcre2_pattern_info+ :: Ptr Pcre2_code+ -> CUInt -- ^ See below for possible values.+ -> Ptr a+ -> IO CInt -- ^ See below for possible error values.++constant "INFO_ALLOPTIONS" ''CUInt+constant "INFO_ARGOPTIONS" ''CUInt+constant "INFO_EXTRAOPTIONS" ''CUInt+constant "INFO_BACKREFMAX" ''CUInt+constant "INFO_BSR" ''CUInt+constant "INFO_CAPTURECOUNT" ''CUInt+constant "INFO_DEPTHLIMIT" ''CUInt+constant "INFO_FIRSTBITMAP" ''CUInt+constant "INFO_FIRSTCODETYPE" ''CUInt+constant "INFO_FIRSTCODEUNIT" ''CUInt+constant "INFO_FRAMESIZE" ''CUInt+constant "INFO_HASBACKSLASHC" ''CUInt+constant "INFO_HASCRORLF" ''CUInt+constant "INFO_HEAPLIMIT" ''CUInt+constant "INFO_JCHANGED" ''CUInt+constant "INFO_JITSIZE" ''CUInt+constant "INFO_LASTCODETYPE" ''CUInt+constant "INFO_LASTCODEUNIT" ''CUInt+constant "INFO_MATCHEMPTY" ''CUInt+constant "INFO_MATCHLIMIT" ''CUInt+constant "INFO_MAXLOOKBEHIND" ''CUInt+constant "INFO_MINLENGTH" ''CUInt+constant "INFO_NAMECOUNT" ''CUInt+constant "INFO_NAMEENTRYSIZE" ''CUInt+constant "INFO_NAMETABLE" ''CUInt+constant "INFO_NEWLINE" ''CUInt+constant "INFO_SIZE" ''CUInt++constant "ERROR_UNSET" ''CInt++-- ** Duplicate capture group names+foreign import capi unsafe "pcre2.h" pcre2_substring_nametable_scan+ :: Ptr Pcre2_code+ -> PCRE2_SPTR -- ^ name+ -> Ptr PCRE2_SPTR -- ^ first+ -> Ptr PCRE2_SPTR -- ^ last+ -> IO CInt++-- * Callouts++foreign import capi safe "pcre2.h" pcre2_callout_enumerate+ :: Ptr Pcre2_code+ -> FunPtr (Ptr Pcre2_callout_enumerate_block -> Ptr a -> IO CInt)+ -> Ptr a+ -> IO CInt++-- ** Callout struct getters+--+-- $CalloutStructGetters+-- These functions are not part of the official API; we provide them here. C+-- API consumers are supposed to access struct fields directly, but the FFI+-- cannot yet do that as of GHC 8.8.4.++-- *** @pcre2_callout_block@+getter "callout_block" "version" ''CUInt+getter "callout_block" "callout_number" ''CUInt+getter "callout_block" "capture_top" ''CUInt+getter "callout_block" "capture_last" ''CUInt+getter "callout_block" "callout_flags" ''CUInt+-- ^ See below for possible bit flags.+constant "CALLOUT_STARTMATCH" ''CUInt+constant "CALLOUT_BACKTRACK" ''CUInt+foreign import capi unsafe "getters.h" pcre2_callout_block_offset_vector+ :: Ptr Pcre2_callout_block+ -> IO (Ptr PCRE2_SIZE)+getter "callout_block" "mark" ''PCRE2_SPTR+getter "callout_block" "subject" ''PCRE2_SPTR+getter "callout_block" "subject_length" ''PCRE2_SIZE+getter "callout_block" "start_match" ''PCRE2_SIZE+getter "callout_block" "current_position" ''PCRE2_SIZE+getter "callout_block" "pattern_position" ''PCRE2_SIZE+getter "callout_block" "next_item_length" ''PCRE2_SIZE+getter "callout_block" "callout_string_offset" ''PCRE2_SIZE+getter "callout_block" "callout_string_length" ''PCRE2_SIZE+getter "callout_block" "callout_string" ''PCRE2_SPTR++-- *** @pcre2_callout_enumerate_block@+getter "callout_enumerate_block" "version" ''CUInt+getter "callout_enumerate_block" "pattern_position" ''PCRE2_SIZE+getter "callout_enumerate_block" "next_item_length" ''PCRE2_SIZE+getter "callout_enumerate_block" "callout_number" ''CUInt+getter "callout_enumerate_block" "callout_string_offset" ''PCRE2_SIZE+getter "callout_enumerate_block" "callout_string_length" ''PCRE2_SIZE+getter "callout_enumerate_block" "callout_string" ''PCRE2_SPTR++-- *** @pcre2_substitute_callout_block@+getter "substitute_callout_block" "version" ''CUInt+getter "substitute_callout_block" "subscount" ''CUInt+getter "substitute_callout_block" "input" ''PCRE2_SPTR+getter "substitute_callout_block" "output" ''PCRE2_SPTR+foreign import capi unsafe "getters.h" pcre2_substitute_callout_block_ovector+ :: Ptr Pcre2_substitute_callout_block+ -> IO (Ptr PCRE2_SIZE)+getter "substitute_callout_block" "oveccount" ''CUInt+foreign import capi unsafe "getters.h"+ pcre2_substitute_callout_block_output_offsets+ :: Ptr Pcre2_substitute_callout_block+ -> IO (Ptr PCRE2_SIZE) -- ^ Array of 2 (@PCRE2_SIZE[2]@)++-- * The match data block++foreign import capi safe "pcre2.h" pcre2_match_data_create+ :: CUInt -- ^ ovecsize+ -> Ptr Pcre2_general_context+ -> IO (Ptr Pcre2_match_data)++foreign import capi safe "pcre2.h" pcre2_match_data_create_from_pattern+ :: Ptr Pcre2_code+ -> Ptr Pcre2_general_context+ -> IO (Ptr Pcre2_match_data)++foreign import capi safe "pcre2.h" pcre2_match_data_free+ :: Ptr Pcre2_match_data+ -> IO ()++-- * Matching a pattern++foreign import capi safe "pcre2.h" pcre2_match+ :: Ptr Pcre2_code+ -> PCRE2_SPTR -- ^ subject+ -> PCRE2_SIZE -- ^ length+ -> PCRE2_SIZE -- ^ startoffset+ -> CUInt -- ^ See below for possible bit flags.+ -> Ptr Pcre2_match_data+ -> Ptr Pcre2_match_context+ -> IO CInt++-- ** Match options+constant "COPY_MATCHED_SUBJECT" ''CUInt+constant "NOTBOL" ''CUInt+constant "NOTEOL" ''CUInt+constant "NOTEMPTY" ''CUInt+constant "NOTEMPTY_ATSTART" ''CUInt+constant "NO_JIT" ''CUInt+constant "PARTIAL_HARD" ''CUInt+constant "PARTIAL_SOFT" ''CUInt++-- ** Match errors+constant "ERROR_NOMATCH" ''CInt+constant "ERROR_PARTIAL" ''CInt+constant "ERROR_BADMAGIC" ''CInt+constant "ERROR_BADMODE" ''CInt+constant "ERROR_BADOFFSET" ''CInt+constant "ERROR_BADOPTION" ''CInt+constant "ERROR_BADUTFOFFSET" ''CInt+constant "ERROR_CALLOUT" ''CInt+constant "ERROR_DEPTHLIMIT" ''CInt+constant "ERROR_HEAPLIMIT" ''CInt+constant "ERROR_INTERNAL" ''CInt+constant "ERROR_JIT_STACKLIMIT" ''CInt+constant "ERROR_MATCHLIMIT" ''CInt+constant "ERROR_NOMEMORY" ''CInt+constant "ERROR_NULL" ''CInt+-- *** UTF-16-specific errors+--+-- | \"Missing low surrogate at end of string\"+constant "ERROR_UTF16_ERR1" ''CInt+-- | \"Invalid low surrogate follows high surrogate\"+constant "ERROR_UTF16_ERR2" ''CInt+-- | \"Isolated low surrogate\"+constant "ERROR_UTF16_ERR3" ''CInt++-- * DFA matching++foreign import capi safe "pcre2.h" pcre2_dfa_match+ :: Ptr Pcre2_code+ -> PCRE2_SPTR -- ^ subject+ -> PCRE2_SIZE -- ^ length+ -> PCRE2_SIZE -- ^ startoffset+ -> CUInt -- ^ options+ -> Ptr Pcre2_match_data+ -> Ptr Pcre2_match_context+ -> Ptr CInt -- ^ workspace+ -> PCRE2_SIZE -- ^ wscount+ -> IO CInt++-- ** DFA matching options+constant "DFA_SHORTEST" ''CUInt+constant "DFA_RESTART" ''CUInt++-- ** DFA matching errors+constant "ERROR_DFA_UFUNC" ''CInt+constant "ERROR_DFA_UITEM" ''CInt+constant "ERROR_DFA_UCOND" ''CInt+constant "ERROR_DFA_UINVALID_UTF" ''CInt+constant "ERROR_DFA_WSSIZE" ''CInt+constant "ERROR_DFA_RECURSE" ''CInt+constant "ERROR_DFA_BADRESTART" ''CInt++-- * Returned string and captured substrings++foreign import capi unsafe "pcre2.h" pcre2_get_ovector_count+ :: Ptr Pcre2_match_data+ -> IO CUInt++foreign import capi unsafe "pcre2.h" pcre2_get_ovector_pointer+ :: Ptr Pcre2_match_data+ -> IO (Ptr PCRE2_SIZE)++foreign import capi unsafe "pcre2.h" pcre2_substring_length_bynumber+ :: Ptr Pcre2_match_data+ -> CUInt -- ^ number+ -> Ptr PCRE2_SIZE -- ^ length+ -> IO CInt++foreign import capi safe "pcre2.h" pcre2_substring_copy_bynumber+ :: Ptr Pcre2_match_data+ -> CUInt -- ^ number+ -> Ptr PCRE2_UCHAR -- ^ buffer+ -> Ptr PCRE2_SIZE -- ^ bufflen+ -> IO CInt++foreign import capi safe "pcre2.h" pcre2_substring_get_bynumber+ :: Ptr Pcre2_match_data+ -> CUInt -- ^ name+ -> Ptr (Ptr PCRE2_UCHAR) -- ^ bufferptr+ -> Ptr PCRE2_SIZE -- ^ bufflen+ -> IO CInt++foreign import capi unsafe "pcre2.h" pcre2_substring_list_get+ :: Ptr Pcre2_match_data+ -> Ptr (Ptr (Ptr PCRE2_UCHAR)) -- ^ listptr+ -> Ptr (Ptr PCRE2_SIZE) -- ^ lengthsptr+ -> IO CInt++foreign import capi safe "pcre2.h" pcre2_substring_list_free+ :: Ptr PCRE2_SPTR+ -> IO ()++foreign import capi unsafe "pcre2.h" pcre2_substring_number_from_name+ :: Ptr Pcre2_code+ -> PCRE2_SPTR -- ^ name+ -> IO CInt++foreign import capi unsafe "pcre2.h" pcre2_substring_length_byname+ :: Ptr Pcre2_match_data+ -> PCRE2_SPTR -- ^ name+ -> Ptr PCRE2_SIZE -- ^ length+ -> IO CInt++foreign import capi safe "pcre2.h" pcre2_substring_copy_byname+ :: Ptr Pcre2_match_data+ -> PCRE2_SPTR -- ^ name+ -> Ptr PCRE2_UCHAR -- ^ buffer+ -> Ptr PCRE2_SIZE -- ^ bufflen+ -> IO CInt++foreign import capi safe "pcre2.h" pcre2_substring_get_byname+ :: Ptr Pcre2_match_data+ -> PCRE2_SPTR -- ^ name+ -> Ptr (Ptr PCRE2_UCHAR) -- ^ bufferptr+ -> Ptr PCRE2_SIZE -- ^ bufflen+ -> IO CInt++-- NOTE Maybe after all other substring functions?+foreign import capi safe "pcre2.h" pcre2_substring_free+ :: Ptr PCRE2_UCHAR+ -> IO ()++constant "ERROR_NOSUBSTRING" ''CInt+constant "ERROR_NOUNIQUESUBSTRING" ''CInt+constant "ERROR_UNAVAILABLE" ''CInt++-- * Creating a new string with substitutions++foreign import capi safe "pcre2.h" pcre2_substitute+ :: Ptr Pcre2_code+ -> PCRE2_SPTR -- ^ subject+ -> PCRE2_SIZE -- ^ length+ -> PCRE2_SIZE -- ^ startoffset+ -> CUInt -- ^ options+ -> Ptr Pcre2_match_data+ -> Ptr Pcre2_match_context+ -> PCRE2_SPTR -- ^ replacement+ -> PCRE2_SIZE -- ^ rlength+ -> Ptr PCRE2_UCHAR -- ^ outputbuffer+ -> Ptr PCRE2_SIZE -- ^ outlengthptr+ -> IO CInt++-- ** Substitution options+constant "SUBSTITUTE_REPLACEMENT_ONLY" ''CUInt+constant "SUBSTITUTE_GLOBAL" ''CUInt+constant "SUBSTITUTE_MATCHED" ''CUInt+constant "SUBSTITUTE_OVERFLOW_LENGTH" ''CUInt+constant "SUBSTITUTE_LITERAL" ''CUInt+constant "SUBSTITUTE_UNKNOWN_UNSET" ''CUInt+constant "SUBSTITUTE_UNSET_EMPTY" ''CUInt+constant "SUBSTITUTE_EXTENDED" ''CUInt++-- ** Substitution errors+constant "ERROR_BADREPLACEMENT" ''CInt+constant "ERROR_BADREPESCAPE" ''CInt+constant "ERROR_BADSUBSTITUTION" ''CInt+constant "ERROR_BADSUBSPATTERN" ''CInt++-- * Other information about a match++foreign import capi unsafe "pcre2.h" pcre2_get_mark+ :: Ptr Pcre2_match_data+ -> IO PCRE2_SPTR++foreign import capi unsafe "pcre2.h" pcre2_get_startchar+ :: Ptr Pcre2_match_data+ -> IO PCRE2_SIZE++-- * Obtaining a textual error message+foreign import capi safe "pcre2.h" pcre2_get_error_message+ :: CInt+ -> Ptr PCRE2_UCHAR+ -> PCRE2_SIZE+ -> IO CInt
+ src/hs/Text/Regex/Pcre2/Foreign/TH.hs view
@@ -0,0 +1,37 @@+module Text.Regex.Pcre2.Foreign.TH where++import Language.Haskell.TH++{-+ For example,+constant "ERROR_NOMATCH" ''CInt+ will produce+foreign import capi unsafe "pcre2.h value PCRE2_ERROR_NOMATCH"+ pcre2_ERROR_NOMATCH :: CInt+-}+constant :: String -> Name -> DecsQ+constant suffix typeName = return [dec] where+ dec = ForeignD $ ImportF CApi Unsafe str name ty+ str = "pcre2.h value PCRE2_" ++ suffix+ name = mkName $ "pcre2_" ++ suffix+ ty = ConT typeName++{-+ For example,+getter "callout_block" "version" ''CUInt+ will produce+foreign import capi unsafe "getters.h" pcre2_callout_block_version+ :: Ptr Pcre2_callout_block+ -> IO CUInt+-}+getter :: String -> String -> Name -> DecsQ+getter blockSuffix field typeName = return [dec] where+ dec = ForeignD $ ImportF CApi Unsafe "getters.h" name ty+ name = mkName $ "pcre2_" ++ blockSuffix ++ "_" ++ field+ ty = AppT+ (AppT ArrowT $ AppT+ (ConT $ mkName "Ptr")+ (ConT $ mkName $ "Pcre2_" ++ blockSuffix))+ (AppT+ (ConT $ mkName "IO")+ (ConT typeName))
+ src/hs/Text/Regex/Pcre2/Internal.hs view
@@ -0,0 +1,1410 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++module Text.Regex.Pcre2.Internal where++import Control.Applicative (Alternative(..))+import Control.Exception hiding (TypeError)+import Control.Monad.State.Strict+import Data.Either (partitionEithers)+import Data.Function ((&))+import Data.Functor ((<&>))+import Data.Functor.Const (Const(..))+import Data.Functor.Identity (Identity(..))+import Data.IORef+import Data.IntMap.Strict (IntMap)+import qualified Data.IntMap.Strict as IM+import Data.List (foldl', intercalate)+import Data.List.NonEmpty (NonEmpty(..))+import qualified Data.List.NonEmpty as NE+import Data.Maybe (fromJust, fromMaybe)+import Data.Monoid (Alt(..), Any(..), First(..))+import Data.Proxy (Proxy(..))+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Text.Foreign as Text+import Data.Type.Bool (type (||), If)+import Data.Type.Equality (type (==))+import Data.Typeable (cast)+import Foreign+import Foreign.C.Types+import qualified Foreign.Concurrent as Conc+import GHC.TypeLits hiding (Text)+import qualified GHC.TypeLits as TypeLits+import System.IO.Unsafe (unsafePerformIO)+import Text.Regex.Pcre2.Foreign++-- * General utilities++-- | There is no @nullForeignPtr@ to pass to `withForeignPtr`, so we have to+-- fake it with a `Maybe`.+withForeignOrNullPtr :: Maybe (ForeignPtr a) -> (Ptr a -> IO b) -> IO b+withForeignOrNullPtr Nothing = \action -> action nullPtr+withForeignOrNullPtr (Just fp) = withForeignPtr fp++-- | Helper so we never leak untracked 'Ptr's.+mkForeignPtr :: (Ptr a -> IO ()) -> IO (Ptr a) -> IO (ForeignPtr a)+mkForeignPtr finalize create = create >>= Conc.newForeignPtr <*> finalize++-- | Helper so we never leak untracked 'FunPtr's.+mkFunPtr :: ForeignPtr b -> IO (FunPtr a) -> IO (FunPtr a)+mkFunPtr anchor create = do+ fPtr <- create+ Conc.addForeignPtrFinalizer anchor $ freeHaskellFunPtr fPtr+ return fPtr++safeLast :: [a] -> Maybe a+safeLast [] = Nothing+safeLast xs = Just $ last xs++bitOr :: (Foldable t, Num a, Bits a) => t a -> a+bitOr = foldl' (.|.) 0++-- | Equivalent to @flip fix@.+--+-- Used to express a recursive function of one argument that is called only once+-- on an initial value:+--+-- > let go x = ... in go x0+--+-- as:+--+-- > fix1 x0 $ \go x -> ...+fix1 :: a -> ((a -> b) -> a -> b) -> b+fix1 x f = fix f x++-- | Like `fix1`, but for a function of two arguments. Currently unused.+fix2 :: a -> b -> ((a -> b -> c) -> a -> b -> c) -> c+fix2 x y f = fix f x y++-- | Like `fix1`, but for a function of three arguments. Currently unused.+fix3 :: a -> b -> c -> ((a -> b -> c -> d) -> a -> b -> c -> d) -> d+fix3 x y z f = fix f x y z++-- ** Fast @Text@ slicing++data SliceRange = SliceRange+ {-# UNPACK #-} !Text.I16+ {-# UNPACK #-} !Text.I16++-- | Zero-copy slice a 'Text'. An unset capture is represented by a+-- `pcre2_UNSET` range and is interpreted in this library as `Text.empty`.+thinSlice :: Text -> SliceRange -> Text+thinSlice text (SliceRange off offEnd)+ | off == fromIntegral pcre2_UNSET = Text.empty+ | otherwise = text+ & Text.dropWord16 off+ & Text.takeWord16 (offEnd - off)++-- | Slice a 'Text', copying if it\'s less than half of the original.+slice :: Text -> SliceRange -> Text+slice text sliceRange =+ let substring = thinSlice text sliceRange+ in if Text.length substring > Text.length text `div` 2+ then substring+ else Text.copy substring++-- | Probably unnecessary, but unrestricted 'castPtr' feels dangerous.+class CastCUs a b | a -> b where+ castCUs :: Ptr a -> Ptr b+ castCUs = castPtr+ {-# INLINE castCUs #-}+instance CastCUs CUShort Word16+instance CastCUs Word16 CUShort++-- ** Lens types and utilities+--+-- $LensTypesAndUtilities+-- The combinators\' types are excessively polymorphic\/polykinded\/ugly because+-- they have no accompanying signatures (not worth the trouble).++type Lens' s a = forall f. (Functor f) => (a -> f a) -> s -> f s+type Traversal' s a = forall f. (Applicative f) => (a -> f a) -> s -> f s++preview l = getFirst . getConst . l (Const . First . Just)+view l = getConst . l Const+to k f = Const . getConst . f . k+has l = getAny . getConst . l (\_ -> Const $ Any True)++-- toAlternativeOf :: (Alternative f) => Getting (Alt f a) s a -> s -> f a+toAlternativeOf l = getAlt . view (l . to (Alt . pure))++_headNE :: Lens' (NonEmpty a) a+_headNE f (x :| xs) = f x <&> \x' -> x' :| xs++-- * Assembling inputs into @Matcher@s and @Subber@s++-- | A matching function where all inputs and auxilliary data structures have+-- been \"compiled\". It takes a subject and produces a raw result code and+-- match data, to be passed to further validation and inspection.+type Matcher = Text -> IO (CInt, MatchData)++-- | A substitution function. It takes a subject and produces the number of+-- substitutions performed (0 or 1, or more in the presence of `SubGlobal`)+-- along with the transformed subject. Currently the number is unused.+type Subber = Text -> IO (CInt, Text)++-- ** Options++-- | A `Monoid` representing nearly every facility PCRE2 presents for tweaking+-- the behavior of regex compilation and execution.+--+-- All library functions that take options have the suffix @Opt@ in their names;+-- for each of them, there\'s also a non-@Opt@ convenience function that simply+-- has the (unexported) `mempty` option. For many uses, options won\'t be+-- needed.+--+-- Some options can be enabled by special character sequences in the pattern as+-- an alternative to specifying them as an `Option`. See `Caseless` for+-- example.+--+-- Documentation is scant here. For more complete, accurate information,+-- including discussions of corner cases arising from specific combinations of+-- options and pattern items, please see the [C API+-- documentation](https://pcre.org/current/doc/html/pcre2api.html).+data Option+ = NoOptions -- ^ `mempty`+ | TwoOptions Option Option -- ^ `<>`++ | AllowEmptyClass -- ^ Make @[]@ not match anything, rather than counting+ -- the @]@ as the first character of the class.+ | AltBsux -- ^ Like `AltBsuxLegacy`, except with ECMAScript 6 hex literal+ -- feature for @\\u@.+ | AltBsuxLegacy -- ^ Behave like ECMAScript 5 for @\\U@, @\\u@, and @\\x@.+ -- See 'AltBsux'.+ | AltCircumflex -- ^ Match a @^@ after a newline at the end of the subject.+ -- Only relevant in multiline mode.+ | AltVerbNames -- ^ Enable backslash escapes in verb names. E.g.,+ -- @(*MARK:L\\(O\\)L)@.+ | Anchored -- ^ Equivalent to beginning pattern with @^@.+ | AutoCallout -- ^ Run callout for every pattern item. Only relevant if a+ -- callout is set.+ | BadEscapeIsLiteral -- ^ Do not throw an error for unrecognized or+ -- malformed escapes. /\"This is a dangerous option.\"/+ | Bsr Bsr -- ^ Override what @\\R@ matches (default given by `defaultBsr`).+ | Caseless -- ^ Case-insensitive match. Equivalent to @(?i)@.+ | DepthLimit Word32 -- ^ Override maximum depth of nested backtracking+ -- (default given by `defaultDepthLimit`). Equivalent to+ -- @(*LIMIT_DEPTH=@/number/@)@.+ | DollarEndOnly -- ^ Don\'t match @$@ with a newline at the end of the+ -- subject.+ | DotAll -- ^ A dot also matches a (single-character) newline. Equivalent+ -- to @(?s)@.+ | DupNames -- ^ Allow non-unique capture names.+ | EndAnchored -- ^ More or less like ending pattern with @$@.+ | EscapedCrIsLf -- ^ Interpret @\\r@ as @\\n@.+ | Extended -- ^ In the pattern, ignore whitespace, and enable comments+ -- starting with @#@. Equivalent to @(?x)@.+ | ExtendedMore -- ^ Like `Extended` but also ignore spaces and tabs within+ -- @[]@.+ | FirstLine -- ^ The match must begin in the first line of the subject.+ | HeapLimit Word32 -- ^ Override maximum heap memory (in kibibytes) used to+ -- hold backtracking information (default given by `defaultHeapLimit`).+ -- Equivalent to @(*LIMIT_HEAP=@/number/@)@.+ | Literal -- ^ Treat the pattern as a literal string.+ | MatchLimit Word32 -- ^ Override maximum value of the main matching loop\'s+ -- internal counter (default given by `defaultMatchLimit`), as a simple CPU+ -- throttle. Equivalent to @(*LIMIT_MATCH=@/number/@)@.+ | MatchLine -- ^ Only match complete lines. Equivalent to bracketing the+ -- pattern with @^(?:@/pattern/@)$@.+ | MatchUnsetBackRef -- ^ A backreference to an unset capture group matches+ -- an empty string.+ | MatchWord -- ^ Only match subjects that have word boundaries at the+ -- beginning and end. Equivalent to bracketing the pattern with+ -- @\\b(?:@/pattern/@)\\b@.+ | MaxPatternLength Word64 -- ^ Default is `maxBound`.+ | Multiline -- ^ @^@ and @$@ mean \"beginning\/end of a line\" rather than+ -- \"beginning\/end of the subject\". Equivalent to @(?m)@.+ | NeverBackslashC -- ^ Do not allow the unsafe @\\C@ sequence.+ | NeverUcp -- ^ Don\'t count Unicode characters in some character classes+ -- such as @\\d@. Overrides @(*UCP)@.+ | Newline Newline -- ^ Override what a newline is (default given by+ -- `defaultNewline`). Equivalent to @(*CRLF)@ or similar.+ | NoAutoCapture -- ^ Disable numbered capturing parentheses.+ | NoAutoPossess -- ^ Turn off some optimizations, possibly resulting in some+ -- callouts not being called.+ | NoDotStarAnchor -- ^ Turn off an optimization involving @.*@, possibly+ -- resulting in some callouts not being called.+ | NoStartOptimize -- ^ Turn off some optimizations normally performed at the+ -- beginning of a pattern.+ | NotBol -- ^ First character of subject is not the __b__eginning __o__f+ -- __l__ine. Only affects @^@.+ | NotEmpty -- ^ The 0th capture doesn\'t match if it would be empty.+ | NotEmptyAtStart -- ^ The 0th capture doesn\'t match if it would be empty+ -- and at the beginning of the subject.+ | NotEol -- ^ End of subject is not the __e__nd __o__f __l__ine. Only+ -- affects @$@.+ | OffsetLimit Word64 -- ^ Limit how far an unanchored search can advance in+ -- the subject.+ | ParensLimit Word32 -- ^ Override max depth of nested parentheses (default+ -- given by `defaultParensLimit`).+ | PartialHard -- ^ If the subject ends without finding a complete match,+ -- stop trying alternatives and signal a partial match immediately.+ -- Currently we do this by throwing a `Pcre2Exception` but we should do+ -- better.+ | PartialSoft -- ^ If the subject ends and all alternatives have been tried,+ -- but no complete match is found, signal a partial match. Currently we do+ -- this by throwing a `Pcre2Exception` but we should do better.+ | SubGlobal -- ^ /Affects `subOpt`./ Replace all, rather than just the+ -- first.+ | SubLiteral -- ^ /Affects `subOpt`./ Treat the replacement as a literal+ -- string.+ | SubReplacementOnly -- ^ /Affects `subOpt`./ Return just the rendered+ -- replacement instead of it within the subject. With `SubGlobal`, all+ -- results are concatenated.+ | SubUnknownUnset -- ^ /Affects `subOpt`./ References in the replacement+ -- to non-existent captures don\'t error but are treated as unset.+ | SubUnsetEmpty -- ^ /Affects `subOpt`./ References in the replacement+ -- to unset captures don\'t error but are treated as empty.+ | Ucp -- ^ Count Unicode characters in some character classes such as @\\d@.+ -- Incompatible with `NeverUcp`.+ | Ungreedy -- ^ Invert the effect of @?@. Without it, quantifiers are+ -- non-greedy; with it, they are greedy. Equivalent to @(?U)@.+ | UnsafeCallout (CalloutInfo -> IO CalloutResult) -- ^ Run the given callout+ -- on every capture. Multiples of this option before the rightmost are+ -- ignored.+ --+ -- /NOTE: The callout is run via `unsafePerformIO` within pure code!/+ | UnsafeCompileRecGuard (Int -> IO Bool) -- ^ Run the given guard on every+ -- new descent into a level of parentheses, passing the current depth as+ -- argument. Returning @False@ aborts pattern compilation with an+ -- exception. Multiples of this option before the rightmost are ignored.+ --+ -- /NOTE: Currently (PCRE2 version 10\.35) patterns seem to be parsed in/+ -- /two passes, both times triggering the recursion guard. Also, it is/+ -- /triggered at the beginning of the pattern, passing 0. None of this is/+ -- /documented; expect the unexpected in the presence of side effects!/+ --+ -- /NOTE: The guard is run via `unsafePerformIO` within pure code!/+ | UnsafeSubCallout (SubCalloutInfo -> IO SubCalloutResult) -- ^ Run the+ -- given callout on every substitution. This is at most once unless+ -- `SubGlobal` is set. Multiples of this option before the rightmost are+ -- ignored.+ --+ -- /NOTE: The callout is run via `unsafePerformIO` within pure code!/+ | Utf -- ^ Treat both the pattern and subject as UTF rather than fixed-width+ -- 16-bit code units.++instance Semigroup Option where+ (<>) = TwoOptions++instance Monoid Option where+ mempty = NoOptions++-- | What @\\R@, __b__ack__s__lash __R__, can mean.+data Bsr+ = BsrUnicode -- ^ any Unicode line ending sequence+ | BsrAnyCrlf -- ^ @\\r@, @\\n@, or @\\r\\n@+ deriving (Eq, Show)++-- | C to Haskell.+bsrFromC :: CUInt -> Bsr+bsrFromC x+ | x == pcre2_BSR_UNICODE = BsrUnicode+ | x == pcre2_BSR_ANYCRLF = BsrAnyCrlf+ | otherwise = error $ "bsrFromC: bad value " ++ show x++-- | Haskell to C.+bsrToC :: Bsr -> CUInt+bsrToC BsrUnicode = pcre2_BSR_UNICODE+bsrToC BsrAnyCrlf = pcre2_BSR_ANYCRLF++-- | What\'s considered a newline.+data Newline+ = NewlineCr -- ^ @\\r@ only+ | NewlineLf -- ^ @\\n@ only+ | NewlineCrlf -- ^ @\\r\\n@ only+ | NewlineAny -- ^ any Unicode line ending sequence+ | NewlineAnyCrlf -- ^ any of the above+ | NewlineNul -- ^ binary zero+ deriving (Eq, Show)++-- | C to Haskell.+newlineFromC :: CUInt -> Newline+newlineFromC x+ | x == pcre2_NEWLINE_CR = NewlineCr+ | x == pcre2_NEWLINE_LF = NewlineLf+ | x == pcre2_NEWLINE_CRLF = NewlineCrlf+ | x == pcre2_NEWLINE_ANY = NewlineAny+ | x == pcre2_NEWLINE_ANYCRLF = NewlineAnyCrlf+ | x == pcre2_NEWLINE_NUL = NewlineNul+ | otherwise = error $ "newlineFromC: bad value " ++ show x++-- | Haskell to C.+newlineToC :: Newline -> CUInt+newlineToC NewlineCr = pcre2_NEWLINE_CR+newlineToC NewlineLf = pcre2_NEWLINE_LF+newlineToC NewlineCrlf = pcre2_NEWLINE_CRLF+newlineToC NewlineAny = pcre2_NEWLINE_ANY+newlineToC NewlineAnyCrlf = pcre2_NEWLINE_ANYCRLF+newlineToC NewlineNul = pcre2_NEWLINE_NUL++-- | Input for user-defined callouts.+data CalloutInfo+ = CalloutInfo {+ -- | The index of which capture we\'re on. Note that callouts are never+ -- run for the 0th capture.+ calloutIndex :: CalloutIndex,+ -- | The captures that have been set so far.+ calloutCaptures :: NonEmpty (Maybe Text),+ -- | The original subject.+ calloutSubject :: Text,+ -- | The name of the most recently passed @(*MARK)@, @(*PRUNE)@, or+ -- @(*THEN)@, if any.+ calloutMark :: Maybe Text,+ -- | Is this the first callout after the start of matching?+ calloutIsFirst :: Bool,+ -- | Has a backtrack occurred since the previous callout, or the+ -- beginning of matching if no previous callouts?+ calloutBacktracked :: Bool}+ deriving (Show, Eq)++-- | What caused the callout.+data CalloutIndex+ = CalloutNumber Int -- ^ Numbered capture.+ | CalloutName Text -- ^ Named capture.+ | CalloutAuto Int Int -- ^ The item located at this half-open range of+ -- offsets within the pattern. See `AutoCallout`.+ deriving (Show, Eq)++-- | Callout functions return one of these values, which dictates what happens+-- next in the match.+data CalloutResult+ = CalloutProceed -- ^ Keep going.+ | CalloutNoMatchHere -- ^ Fail the current capture, but not the whole match.+ -- For example, backtracking may occur.+ | CalloutNoMatch -- ^ Fail the whole match.+ deriving (Show, Eq)++-- | Input for user-defined substitution callouts.+data SubCalloutInfo+ = SubCalloutInfo {+ -- | The 1-based index of which substitution we\'re on. Only goes past+ -- 1 during global substitutions.+ subCalloutSubsCount :: Int,+ -- | The captures that have been set so far.+ subCalloutCaptures :: NonEmpty (Maybe Text),+ -- | The original subject.+ subCalloutSubject :: Text,+ -- | The replacement.+ subCalloutReplacement :: Text}+ deriving (Show, Eq)++-- | Substitution callout functions return one of these values, which dictates+-- what happens next in the substitution.+data SubCalloutResult+ = SubCalloutAccept -- ^ Succeed, and keep going if in global mode.+ | SubCalloutSkip -- ^ Do not perform this substitution, but keep going if in+ -- global mode.+ | SubCalloutAbort -- ^ Do not perform this or any subsequent substitutions.+ deriving (Show, Eq)++-- ** Lower-level representation of options and C data++type CompileContext = ForeignPtr Pcre2_compile_context+type Code = ForeignPtr Pcre2_code+type MatchContext = ForeignPtr Pcre2_match_context+type MatchData = ForeignPtr Pcre2_match_data++-- | An `Option` can result in multiple \"plans\".+applyOption :: Option -> [AppliedOption]+applyOption = \case+ NoOptions -> []+ TwoOptions opt0 opt1 -> applyOption opt0 ++ applyOption opt1++ -- CompileOption+ Anchored -> [CompileOption pcre2_ANCHORED]+ AllowEmptyClass -> [CompileOption pcre2_ALLOW_EMPTY_CLASS]+ AltBsuxLegacy -> [CompileOption pcre2_ALT_BSUX]+ AltCircumflex -> [CompileOption pcre2_ALT_CIRCUMFLEX]+ AltVerbNames -> [CompileOption pcre2_ALT_VERBNAMES]+ AutoCallout -> [CompileOption pcre2_AUTO_CALLOUT]+ Caseless -> [CompileOption pcre2_CASELESS]+ DollarEndOnly -> [CompileOption pcre2_DOLLAR_ENDONLY]+ DotAll -> [CompileOption pcre2_DOTALL]+ DupNames -> [CompileOption pcre2_DUPNAMES]+ EndAnchored -> [CompileOption pcre2_ENDANCHORED]+ Extended -> [CompileOption pcre2_EXTENDED]+ ExtendedMore -> [CompileOption pcre2_EXTENDED_MORE]+ FirstLine -> [CompileOption pcre2_FIRSTLINE]+ Literal -> [CompileOption pcre2_LITERAL]+ MatchUnsetBackRef -> [CompileOption pcre2_MATCH_UNSET_BACKREF]+ Multiline -> [CompileOption pcre2_MULTILINE]+ NeverBackslashC -> [CompileOption pcre2_NEVER_BACKSLASH_C]+ NeverUcp -> [CompileOption pcre2_NEVER_UCP]+ NoAutoCapture -> [CompileOption pcre2_NO_AUTO_CAPTURE]+ NoAutoPossess -> [CompileOption pcre2_NO_AUTO_POSSESS]+ NoDotStarAnchor -> [CompileOption pcre2_NO_DOTSTAR_ANCHOR]+ NoStartOptimize -> [CompileOption pcre2_NO_START_OPTIMIZE]+ Ucp -> [CompileOption pcre2_UCP]+ Ungreedy -> [CompileOption pcre2_UNGREEDY]+ Utf -> [CompileOption pcre2_UTF]++ -- ExtraCompileOption+ AltBsux -> [CompileExtraOption pcre2_EXTRA_ALT_BSUX]+ BadEscapeIsLiteral -> [CompileExtraOption pcre2_EXTRA_BAD_ESCAPE_IS_LITERAL]+ EscapedCrIsLf -> [CompileExtraOption pcre2_EXTRA_ESCAPED_CR_IS_LF]+ MatchLine -> [CompileExtraOption pcre2_EXTRA_MATCH_LINE]+ MatchWord -> [CompileExtraOption pcre2_EXTRA_MATCH_WORD]++ -- CompileContextOption+ Bsr bsr -> unary+ CompileContextOption pcre2_set_bsr (bsrToC bsr)+ MaxPatternLength len -> unary+ CompileContextOption pcre2_set_max_pattern_length (fromIntegral len)+ Newline newline -> unary+ CompileContextOption pcre2_set_newline (newlineToC newline)+ ParensLimit limit -> unary+ CompileContextOption pcre2_set_parens_nest_limit (fromIntegral limit)++ -- CompileRecGuardOption+ UnsafeCompileRecGuard f -> [CompileRecGuardOption f]++ -- MatchOption+ NotBol -> [MatchOption pcre2_NOTBOL]+ NotEol -> [MatchOption pcre2_NOTEOL]+ NotEmpty -> [MatchOption pcre2_NOTEMPTY]+ NotEmptyAtStart -> [MatchOption pcre2_NOTEMPTY_ATSTART]+ PartialHard -> [MatchOption pcre2_PARTIAL_HARD]+ PartialSoft -> [MatchOption pcre2_PARTIAL_SOFT]+ SubReplacementOnly -> [MatchOption pcre2_SUBSTITUTE_REPLACEMENT_ONLY]+ SubGlobal -> [MatchOption pcre2_SUBSTITUTE_GLOBAL]+ SubLiteral -> [MatchOption pcre2_SUBSTITUTE_LITERAL]+ SubUnknownUnset -> [MatchOption pcre2_SUBSTITUTE_UNKNOWN_UNSET]+ SubUnsetEmpty -> [MatchOption pcre2_SUBSTITUTE_UNSET_EMPTY]++ -- CalloutOption+ UnsafeCallout f -> [CalloutOption f]++ -- SubCalloutOption+ UnsafeSubCallout f -> [SubCalloutOption f]++ -- MatchContextOption+ OffsetLimit limit -> CompileOption pcre2_USE_OFFSET_LIMIT : unary+ MatchContextOption pcre2_set_offset_limit (fromIntegral limit)+ HeapLimit limit -> unary+ MatchContextOption pcre2_set_heap_limit (fromIntegral limit)+ MatchLimit limit -> unary+ MatchContextOption pcre2_set_match_limit (fromIntegral limit)+ DepthLimit limit -> unary+ MatchContextOption pcre2_set_depth_limit (fromIntegral limit)++ where+ unary ctor f x = (: []) $ ctor $ \ctx -> withForeignPtr ctx $ \ctxPtr ->+ f ctxPtr x >>= check (== 0)++-- | Intermediate representation of options expressing what effect they\'ll have+-- on which stage of regex compilation\/execution. Also provide fake @Prism'@s.+data AppliedOption+ = CompileOption CUInt+ | CompileExtraOption CUInt+ | CompileContextOption (CompileContext -> IO ())+ | CompileRecGuardOption (Int -> IO Bool)+ | MatchOption CUInt+ | CalloutOption (CalloutInfo -> IO CalloutResult)+ | SubCalloutOption (SubCalloutInfo -> IO SubCalloutResult)+ | MatchContextOption (MatchContext -> IO ())++_CompileOption f =+ \case CompileOption x -> CompileOption <$> f x; o -> pure o+_CompileExtraOption f =+ \case CompileExtraOption x -> CompileExtraOption <$> f x; o -> pure o+_CompileContextOption f =+ \case CompileContextOption x -> CompileContextOption <$> f x; o -> pure o+_CompileRecGuardOption f =+ \case CompileRecGuardOption x -> CompileRecGuardOption <$> f x; o -> pure o+_MatchOption f =+ \case MatchOption x -> MatchOption <$> f x; o -> pure o+_CalloutOption f =+ \case CalloutOption x -> CalloutOption <$> f x; o -> pure o+_SubCalloutOption f =+ \case SubCalloutOption x -> SubCalloutOption <$> f x; o -> pure o+_MatchContextOption f =+ \case MatchContextOption x -> MatchContextOption <$> f x; o -> pure o++-- ** Extracting options at the right times+--+-- $ExtractingOptionsAtTheRightTimes+-- We interleave the extraction of options with the manipulation of foreign data+-- en route to the target `Matcher` or `Subber`.++-- | A `Monad` modeling both option extraction and foreign effects.+type ExtractOpts = StateT [AppliedOption] IO++-- | Use a fake @Prism'@ to extract a category of options.+extractOptsOf :: Traversal' AppliedOption a -> ExtractOpts [a]+extractOptsOf traversal = state $ partitionEithers . map discrim where+ discrim opt = maybe (Right opt) Left $ preview traversal opt++-- | Prepare to compile a `Code`.+extractCompileEnv :: ExtractOpts CompileEnv+extractCompileEnv = do+ ctxUpds <- extractOptsOf _CompileContextOption+ xtraOpts <- bitOr <$> extractOptsOf _CompileExtraOption+ recGuard <- safeLast <$> extractOptsOf _CompileRecGuardOption++ compileEnvCtx <- sequence $ do+ guard $ not $ null ctxUpds && xtraOpts == 0 && null recGuard+ Just $ liftIO $ do+ ctx <- mkForeignPtr pcre2_compile_context_free $+ pcre2_compile_context_create nullPtr++ forM_ ctxUpds $ \update -> update ctx+ when (xtraOpts /= 0) $ withForeignPtr ctx $ \ctxPtr ->+ pcre2_set_compile_extra_options ctxPtr xtraOpts >>= check (== 0)++ return ctx++ compileEnvERef <- sequence $ do+ ctx <- compileEnvCtx+ f <- recGuard+ Just $ liftIO $ do+ eRef <- newIORef Nothing+ fPtr <- mkFunPtr ctx $ mkRecursionGuard $ \depth _ -> do+ resultOrE <- try $ do+ f <- evaluate f+ result <- f $ fromIntegral depth+ evaluate result+ case resultOrE of+ Right success -> return $ if success then 0 else 1+ Left e -> writeIORef eRef (Just e) >> return 1++ withForeignPtr ctx $ \ctxPtr -> do+ result <- pcre2_set_compile_recursion_guard ctxPtr fPtr nullPtr+ check (== 0) result++ return eRef++ return $ CompileEnv {..}++-- | Inputs to `Code` compilation besides the pattern.+data CompileEnv = CompileEnv {+ compileEnvCtx :: Maybe CompileContext,+ -- | A register for catching exceptions thrown in recursion guards, if+ -- needed.+ compileEnvERef :: Maybe (IORef (Maybe SomeException))}++-- | Compile a `Code`.+extractCode :: Text -> CompileEnv -> ExtractOpts Code+extractCode patt (CompileEnv {..}) = do+ opts <- bitOr <$> extractOptsOf _CompileOption++ liftIO $ mkForeignPtr pcre2_code_free $+ Text.useAsPtr patt $ \pattPtr pattCUs ->+ alloca $ \errorCodePtr ->+ alloca $ \errorOffPtr ->+ withForeignOrNullPtr compileEnvCtx $ \ctxPtr -> do+ codePtr <- pcre2_compile+ (castCUs pattPtr)+ (fromIntegral pattCUs)+ opts+ errorCodePtr+ errorOffPtr+ ctxPtr+ when (codePtr == nullPtr) $ do+ -- Re-throw exception (if any) from recursion guard (if any)+ forM_ compileEnvERef $ readIORef >=> mapM_ throwIO+ -- Otherwise throw PCRE2 error+ errorCode <- peek errorCodePtr+ offCUs <- peek errorOffPtr+ throwIO $ Pcre2CompileException errorCode patt offCUs++ return codePtr++-- | `Code` and auxiliary compiled data used in preparation for a match or+-- substitution. This remains constant for the lifetime of a `Matcher` or+-- `Subber`.+data MatchEnv = MatchEnv {+ matchEnvCode :: Code,+ matchEnvOpts :: CUInt,+ matchEnvCtx :: Maybe MatchContext,+ matchEnvCallout :: Maybe (CalloutInfo -> IO CalloutResult),+ matchEnvSubCallout :: Maybe (SubCalloutInfo -> IO SubCalloutResult)}++-- | Prepare a matching function.+extractMatchEnv :: Code -> ExtractOpts MatchEnv+extractMatchEnv matchEnvCode = do+ matchEnvOpts <- bitOr <$> extractOptsOf _MatchOption++ matchEnvCtx <- extractOptsOf _MatchContextOption >>= \case+ [] -> return Nothing+ ctxUpds -> liftIO $ Just <$> do+ ctx <- mkForeignPtr pcre2_match_context_free $+ pcre2_match_context_create nullPtr++ forM_ ctxUpds $ \update -> update ctx++ return ctx++ matchEnvCallout <- safeLast <$> extractOptsOf _CalloutOption+ matchEnvSubCallout <- safeLast <$> extractOptsOf _SubCalloutOption++ return $ MatchEnv {..}++-- | Helper for @assemble*@ functions. Basically, extract all options and help+-- produce a function that takes a `Text` subject and does something.+assembleSubjFun+ :: (MatchEnv -> Text -> IO a)+ -> Option+ -> Text+ -> IO (Text -> IO a)+assembleSubjFun mkSubjFun option patt =+ runStateT extractAll (applyOption option) <&> \case+ (subjFun, []) -> subjFun+ _ -> error "BUG! Options not fully extracted"++ where+ extractAll = do+ compileEnv <- extractCompileEnv+ code <- extractCode patt compileEnv+ matchEnv <- extractMatchEnv code++ return $ mkSubjFun matchEnv++-- | Produce a `Matcher`.+assembleMatcher+ :: Option+ -> Text -- ^ pattern+ -> IO Matcher+assembleMatcher = assembleSubjFun $ \matchEnv@(MatchEnv {..}) ->+ let matchTempEnvWithSubj = mkMatchTempEnv matchEnv+ in \subject -> withForeignPtr matchEnvCode $ \codePtr -> do+ matchData <- mkForeignPtr pcre2_match_data_free $+ pcre2_match_data_create_from_pattern codePtr nullPtr++ MatchTempEnv {..} <- matchTempEnvWithSubj subject+ result <-+ Text.useAsPtr subject $ \subjPtr subjCUs ->+ withForeignOrNullPtr matchTempEnvCtx $ \ctxPtr ->+ withForeignPtr matchData $ \matchDataPtr -> pcre2_match+ codePtr+ (castCUs subjPtr)+ (fromIntegral subjCUs)+ 0+ matchEnvOpts+ matchDataPtr+ ctxPtr+ maybeRethrow matchTempEnvRef++ return (result, matchData)++-- | A `Subber` works by first writing results to a reasonably-sized buffer. If+-- we run out of room, PCRE2 allows us to simulate the rest of the substitution+-- without writing anything, in order to calculate how big the buffer actually+-- has to be. In this event, we rerun the substitution with a new,+-- exactly-sized buffer.+--+-- One potential issue arising from two attempts is running effectful callouts+-- twice. We mitigate this by skipping callouts the second time:+--+-- * all capture callouts, since they had run during the simulation, and+--+-- * those substitution callouts that had run the first time.+--+-- Therefore, the first time, log the substitution callout indexes that had run+-- along with their results, and replay the log the second time, returning those+-- same results without re-incurring effects.+assembleSubber+ :: Text -- ^ replacement+ -> Option+ -> Text -- ^ pattern+ -> IO Subber+assembleSubber replacement =+ assembleSubjFun $ \firstMatchEnv@(MatchEnv {..}) ->+ -- Subber+ \subject ->+ withForeignPtr matchEnvCode $ \codePtr ->+ Text.useAsPtr subject $ \subjPtr subjCUs ->+ Text.useAsPtr replacement $ \replPtr replCUs ->+ alloca $ \outLenPtr -> do+ let checkAndGetOutput :: CInt -> PCRE2_SPTR -> IO (CInt, Text)+ checkAndGetOutput 0 _ = return (0, subject)+ checkAndGetOutput result outBufPtr = do+ check (> 0) result+ outLen <- peek outLenPtr+ out <- Text.fromPtr (castCUs outBufPtr) (fromIntegral outLen)+ return (result, out)++ run :: CUInt -> Ptr Pcre2_match_context -> PCRE2_SPTR -> IO CInt+ run curOpts ctxPtr outBufPtr = pcre2_substitute+ codePtr+ (castCUs subjPtr)+ (fromIntegral subjCUs)+ 0+ (matchEnvOpts .|. curOpts)+ nullPtr+ ctxPtr+ (castCUs replPtr)+ (fromIntegral replCUs)+ outBufPtr+ outLenPtr++ -- Guess the size of the output to be <= 2x that of the subject.+ initOutLen = Text.length subject * 2++ poke outLenPtr $ fromIntegral initOutLen+ MatchTempEnv {..} <- mkMatchTempEnv firstMatchEnv subject+ firstAttempt <- withForeignOrNullPtr matchTempEnvCtx $ \ctxPtr ->+ allocaArray initOutLen $ \outBufPtr -> do+ result <- run pcre2_SUBSTITUTE_OVERFLOW_LENGTH ctxPtr outBufPtr+ maybeRethrow matchTempEnvRef+ if result == pcre2_ERROR_NOMEMORY+ then Left <$> case matchTempEnvRef of+ Nothing -> return IM.empty+ Just ref -> calloutStateSubsLog <$> readIORef ref+ else Right <$> checkAndGetOutput result outBufPtr++ case firstAttempt of+ Right resultAndOutput -> return resultAndOutput+ Left subsLog -> do+ -- The output was bigger than we guessed. Try again.+ computedOutLen <- fromIntegral <$> peek outLenPtr+ let finalMatchEnv = firstMatchEnv {+ -- Do not run capture callouts again.+ matchEnvCallout = Nothing,+ -- Do not run any substitution callouts run previously.+ matchEnvSubCallout = fastFwd <$> matchEnvSubCallout}+ fastFwd f = \info ->+ case subsLog IM.!? subCalloutSubsCount info of+ Just result -> return result+ Nothing -> f info+ MatchTempEnv {..} <- mkMatchTempEnv finalMatchEnv subject+ withForeignOrNullPtr matchTempEnvCtx $ \ctxPtr ->+ allocaArray computedOutLen $ \outBufPtr -> do+ result <- run 0 ctxPtr outBufPtr+ maybeRethrow matchTempEnvRef+ checkAndGetOutput result outBufPtr++-- | Generate per-call data for @pcre2_match()@ etc., to accommodate callouts.+--+-- We need to save and inspect state that occurs in potentially concurrent+-- matches. This means a new state ref for each match, which means a new+-- `FunPtr` to close on it, which means a new match context to set it to.+mkMatchTempEnv+ :: MatchEnv+ -> Text -- ^ Callout info requires access to the original subject.+ -> IO MatchTempEnv+mkMatchTempEnv (MatchEnv {..})+ | null matchEnvCallout && null matchEnvSubCallout = \_ -> return noCallouts+ | otherwise = \subject -> do+ calloutStateRef <- newIORef $ CalloutState {+ calloutStateException = Nothing,+ calloutStateSubsLog = IM.empty}+ ctx <- mkForeignPtr pcre2_match_context_free ctxPtrForCallouts++ -- Install C function pointers in the @pcre2_match_context@. When+ -- dereferenced and called, they will force the user-supplied Haskell+ -- callout functions and their results, catching any exceptions and+ -- saving them.++ -- Install callout, if any+ forM_ matchEnvCallout $ \f -> do+ fPtr <- mkFunPtr ctx $ mkCallout $ \blockPtr _ -> do+ info <- getCalloutInfo subject blockPtr+ resultOrE <- try $ do+ f <- evaluate f+ result <- f info+ evaluate result+ case resultOrE of+ Right result -> return $ case result of+ CalloutProceed -> 0+ CalloutNoMatchHere -> 1+ CalloutNoMatch -> pcre2_ERROR_NOMATCH+ Left e -> do+ modifyIORef' calloutStateRef $ \cst -> cst {+ calloutStateException = Just e}+ return pcre2_ERROR_CALLOUT+ withForeignPtr ctx $ \ctxPtr ->+ pcre2_set_callout ctxPtr fPtr nullPtr >>= check (== 0)++ -- Install substitution callout, if any+ forM_ matchEnvSubCallout $ \f -> do+ fPtr <- mkFunPtr ctx $ mkCallout $ \blockPtr _ -> do+ info <- getSubCalloutInfo subject blockPtr+ resultOrE <- try $ do+ f <- evaluate f+ result <- f info+ evaluate result+ case resultOrE of+ Right result -> do+ modifyIORef' calloutStateRef $ \cst -> cst {+ calloutStateSubsLog = IM.insert+ (subCalloutSubsCount info)+ result+ (calloutStateSubsLog cst)}+ return $ case result of+ SubCalloutAccept -> 0+ SubCalloutSkip -> 1+ SubCalloutAbort -> -1+ Left e -> do+ modifyIORef' calloutStateRef $ \cst -> cst {+ calloutStateException = Just e}+ return (-1)+ withForeignPtr ctx $ \ctxPtr -> do+ result <- pcre2_set_substitute_callout ctxPtr fPtr nullPtr+ check (== 0) result++ return $ MatchTempEnv {+ matchTempEnvCtx = Just ctx,+ matchTempEnvRef = Just calloutStateRef}++ where+ noCallouts = MatchTempEnv {+ matchTempEnvCtx = matchEnvCtx,+ matchTempEnvRef = Nothing}+ ctxPtrForCallouts = case matchEnvCtx of+ -- No pre-existing match context, so create one afresh.+ Nothing -> pcre2_match_context_create nullPtr+ -- Pre-existing match context, so copy it.+ Just ctx -> withForeignPtr ctx pcre2_match_context_copy++-- | Per-call data for @pcre2_match()@ etc.+data MatchTempEnv = MatchTempEnv {+ matchTempEnvCtx :: Maybe MatchContext,+ matchTempEnvRef :: Maybe (IORef CalloutState)}++-- | Data computed during callouts that will be stashed in an IORef and+-- inspected after @pcre2_match()@ or similar completes.+data CalloutState = CalloutState {+ calloutStateException :: Maybe SomeException,+ calloutStateSubsLog :: IntMap SubCalloutResult}++-- | FFI wrapper.+foreign import ccall "wrapper" mkRecursionGuard+ :: (CUInt -> Ptr a -> IO CInt)+ -> IO (FunPtr (CUInt -> Ptr a -> IO CInt))++-- | FFI wrapper.+foreign import ccall "wrapper" mkCallout+ :: (Ptr block -> Ptr a -> IO CInt)+ -> IO (FunPtr (Ptr block -> Ptr a -> IO CInt))++-- | Within a callout, marshal the original subject and @pcre2_callout_block@+-- data to Haskell and present to the user function. Ensure no pointers are+-- leaked!+getCalloutInfo :: Text -> Ptr Pcre2_callout_block -> IO CalloutInfo+getCalloutInfo subject blockPtr = do+ calloutIndex <- do+ str <- pcre2_callout_block_callout_string blockPtr+ if str == nullPtr+ then pcre2_callout_block_callout_number blockPtr >>= \case+ -- Auto callout+ 255 -> liftM2 CalloutAuto pattPos itemLen where+ pattPos = intVia pcre2_callout_block_pattern_position+ itemLen = intVia pcre2_callout_block_next_item_length+ intVia getter = fromIntegral <$> getter blockPtr+ -- Numerical callout+ number -> return $ CalloutNumber $ fromIntegral number+ else do+ -- String callout+ len <- pcre2_callout_block_callout_string_length blockPtr+ CalloutName <$> Text.fromPtr (castCUs str) (fromIntegral len)++ let calloutSubject = subject++ calloutCaptures <- do+ ovecPtr <- pcre2_callout_block_offset_vector blockPtr+ top <- pcre2_callout_block_capture_top blockPtr+ forM (0 :| [1 .. fromIntegral top - 1]) $ \n -> do+ start <- peekElemOff ovecPtr $ n * 2+ if start == pcre2_UNSET+ then return Nothing+ else Just <$> do+ end <- peekElemOff ovecPtr $ n * 2 + 1+ return $ slice calloutSubject $ SliceRange+ (fromIntegral start)+ (fromIntegral end)++ calloutMark <- do+ ptr <- pcre2_callout_block_mark blockPtr+ if ptr == nullPtr+ then return Nothing+ else Just <$> do+ -- TODO Replace this with a more obviously best way to slurp a+ -- zero-terminated region of memory into a `Text`, given+ -- whatever the pcre2callout spec means by "zero-terminated".+ len <- fix1 0 $ \go off -> peekElemOff ptr off >>= \case+ 0 -> return off+ _ -> go $ off + 1+ Text.fromPtr (castCUs ptr) (fromIntegral len)++ flags <- pcre2_callout_block_callout_flags blockPtr+ let calloutIsFirst = flags .&. pcre2_CALLOUT_STARTMATCH /= 0+ calloutBacktracked = flags .&. pcre2_CALLOUT_BACKTRACK /= 0++ return $ CalloutInfo {..}++-- | Within a substitution callout, marshal the original subject and+-- @pcre2_substitute_callout_block@ data to Haskell and present to the user+-- function. Ensure no pointers are leaked!+getSubCalloutInfo+ :: Text -> Ptr Pcre2_substitute_callout_block -> IO SubCalloutInfo+getSubCalloutInfo subCalloutSubject blockPtr = do+ subCalloutSubsCount <-+ fromIntegral <$> pcre2_substitute_callout_block_subscount blockPtr++ subCalloutCaptures <- do+ ovecPtr <- pcre2_substitute_callout_block_ovector blockPtr+ ovecCount <- pcre2_substitute_callout_block_oveccount blockPtr+ forM (0 :| [1 .. fromIntegral ovecCount - 1]) $ \n -> do+ start <- peekElemOff ovecPtr $ n * 2+ if start == pcre2_UNSET+ then return Nothing+ else Just <$> do+ end <- peekElemOff ovecPtr $ n * 2 + 1+ return $ slice subCalloutSubject $ SliceRange+ (fromIntegral start)+ (fromIntegral end)++ subCalloutReplacement <- do+ outPtr <- pcre2_substitute_callout_block_output blockPtr+ offsetsPtr <- pcre2_substitute_callout_block_output_offsets blockPtr+ [start, end] <- forM [0, 1] $ peekElemOff offsetsPtr+ Text.fromPtr+ (castCUs $ advancePtr outPtr $ fromIntegral start)+ (fromIntegral $ end - start)++ return $ SubCalloutInfo {..}++-- | If there was a callout and it threw an exception, rethrow it.+maybeRethrow :: Maybe (IORef CalloutState) -> IO ()+maybeRethrow = mapM_ $ readIORef >=> mapM_ throwIO . calloutStateException++-- * Packaging @Matcher@s and @Subber@s as public API functions++-- | The most general form of a matching function, which can also be used as a+-- @Setter'@ to perform substitutions at the Haskell level.+--+-- When any capture is forced, all captures are forced in order to GC C data+-- more promptly. When we need /some/ captures but not /all/ captures, we can+-- pass in a whitelist of the numbers of captures we want, thereby avoiding+-- unnecessary allocations.+--+-- Internal only! Users should not (have to) know about `Matcher`.+_capturesInternal :: Matcher -> [Int] -> Traversal' Text (NonEmpty Text)+_capturesInternal matcher whitelist f subject+ | result == pcre2_ERROR_NOMATCH = pure subject+ | result <= 0 = throw $ Pcre2Exception result+ | otherwise = f cs <&> \cs' ->+ -- Swag foldl-as-foldr to create only as many segments as we need to+ -- stitch back together and no more.+ let triples = ovecEntries `NE.zip` cs `NE.zip` cs'+ in Text.concat $ foldr mkSegments termSegments triples 0++ where++ (result, matchData) = unsafePerformIO $ matcher subject+ cs = unsafePerformIO $ forM ovecEntries $ evaluate . slice subject+ ovecEntries = unsafePerformIO $ getOvecEntriesAt whitelist matchData++ mkSegments ((SliceRange off offEnd, c), c') r prevOffEnd+ | off == fromIntegral pcre2_UNSET || c == c' =+ -- This substring is unset or unchanged. Keep going without making+ -- cuts.+ r prevOffEnd+ | otherwise =+ -- Emit the subject up until here, and the new substring, and keep+ -- going, remembering where we are now.+ thinSlice subject (SliceRange prevOffEnd off) : c' : r offEnd+ termSegments off =+ let offEnd = fromIntegral $ Text.length subject+ -- If the terminal segment is empty, omit it altogether. That way,+ -- `Text.concat` can just return the subject without copying anything in+ -- cases where no substring is changed.+ in [thinSlice subject (SliceRange off offEnd) | off /= offEnd]++-- | Strictly read specifically indexed captures' offsets from match results.+-- Truncate indexes when they go out of bounds, to support infinite lists.+getOvecEntriesAt :: [Int] -> MatchData -> IO (NonEmpty SliceRange)+getOvecEntriesAt ns matchData = withForeignPtr matchData $ \matchDataPtr -> do+ count <- fromIntegral <$> pcre2_get_ovector_count matchDataPtr++ case NE.nonEmpty $ takeWhile (< count) ns of+ Nothing -> error "BUG! Tried to get empty list of captures"+ Just ns -> do+ ovecPtr <- pcre2_get_ovector_pointer matchDataPtr++ let peekOvec :: Int -> IO Text.I16+ peekOvec = fmap fromIntegral . peekElemOff ovecPtr++ forM ns $ \n -> liftM2 SliceRange+ (peekOvec $ n * 2)+ (peekOvec $ n * 2 + 1)++-- | Helper to create non-Template Haskell API functions. They all take options+-- and a pattern, and then do something via a 'Matcher'.+withMatcher :: (Matcher -> a) -> Option -> Text -> a+withMatcher f option patt = f $ unsafePerformIO $ assembleMatcher option patt++-- | Match a pattern to a subject and return a list of captures, or @[]@ if no+-- match.+captures :: Text -> Text -> [Text]+captures = capturesOpt mempty++-- | @capturesOpt mempty = captures@+capturesOpt :: Option -> Text -> Text -> [Text]+capturesOpt option patt = view $ _capturesOpt option patt . to NE.toList++-- | Match a pattern to a subject and return a non-empty list of captures in an+-- `Alternative`, or `empty` if no match. The non-empty list constructor `:|`+-- serves as a cue to differentiate the 0th capture from the others:+--+-- > let parseDate = capturesA "(\\d{4})-(\\d{2})-(\\d{2})"+-- > in case parseDate "submitted 2020-10-20" of+-- > Just (date :| [y, m, d]) -> ...+-- > Nothing -> putStrLn "didn't match"+capturesA :: (Alternative f) => Text -> Text -> f (NonEmpty Text)+capturesA = capturesOptA mempty++-- | @capturesOptA mempty = capturesA@+capturesOptA :: (Alternative f) => Option -> Text -> Text -> f (NonEmpty Text)+capturesOptA option patt = toAlternativeOf $ _capturesOpt option patt++-- | Does the pattern match the subject?+matches :: Text -> Text -> Bool+matches = matchesOpt mempty++-- | @matchesOpt mempty = matches@+matchesOpt :: Option -> Text -> Text -> Bool+matchesOpt = withMatcher $ \matcher -> has $ _capturesInternal matcher []++-- | Match a pattern to a subject and return the portion that matched in an+-- @Alternative@, or `empty` if no match.+match :: (Alternative f) => Text -> Text -> f Text+match = matchOpt mempty++-- | @matchOpt mempty = match@+matchOpt :: (Alternative f) => Option -> Text -> Text -> f Text+matchOpt option patt = toAlternativeOf $ _matchOpt option patt++-- | Perform at most one substitution. See+-- [the docs](https://pcre.org/current/doc/html/pcre2api.html#SEC36) for the+-- special syntax of /replacement/.+--+-- >>> sub "(\\w+) calling the (\\w+)" "$2 calling the $1" "the pot calling the kettle black"+-- "the kettle calling the pot black"+sub+ :: Text -- ^ pattern+ -> Text -- ^ replacement+ -> Text -- ^ subject+ -> Text -- ^ result+sub = subOpt mempty++-- | Perform substitutions globally.+--+-- >>> gsub "a" "o" "apples and bananas"+-- "opples ond bononos"+gsub :: Text -> Text -> Text -> Text+gsub = subOpt SubGlobal++-- | @+-- subOpt mempty = sub+-- subOpt SubGlobal = gsub+-- @+subOpt :: Option -> Text -> Text -> Text -> Text+subOpt option patt replacement = snd . unsafePerformIO . subber where+ subber = unsafePerformIO $ assembleSubber replacement option patt++-- | Given a pattern, produce an affine traversal (0 or 1 targets) that focuses+-- from a subject to a potential non-empty list of captures.+--+-- Substitution works in the following way: If a capture is set such that the+-- new `Text` is not equal to the old one, a substitution occurs, otherwise it+-- doesn\'t. This matters in cases where a capture encloses another+-- capture—notably, /all/ parenthesized captures are enclosed by the 0th.+--+-- >>> threeAndMiddle = _captures ". (.) ."+-- >>> "A A A" & threeAndMiddle .~ "A A A" :| ["B"]+-- "A B A"+-- >>> "A A A" & threeAndMiddle .~ "A B A" :| ["A"]+-- "A B A"+--+-- Changing multiple overlapping captures won\'t do what you want and is+-- unsupported.+--+-- Changing an unset capture is unsupported because the PCRE2 match API does not+-- give location info about it. Currently we ignore all such attempts. (Native+-- substitution functions like `sub` do not have this limitation. See also+-- `SubUnknownUnset` and `SubUnsetEmpty`.)+--+-- If the list becomes longer for some reason, the extra elements are ignored.+-- If it\'s shortened, the absent elements are considered to be unchanged.+--+-- It's recommended that the list be modified capture-wise,+-- using [@ix@](https://hackage.haskell.org/package/microlens/docs/Lens-Micro.html#v:ix).+--+-- > let madlibs = _captures "(\\w+) my (\\w+)"+-- >+-- > print $ "Well bust my buttons!" &~ do+-- > zoom madlibs $ do+-- > ix 1 . _head .= 'd'+-- > ix 2 %= Text.reverse+-- > _last .= '?'+-- >+-- > -- "Well dust my snottub?"+_captures :: Text -> Traversal' Text (NonEmpty Text)+_captures = _capturesOpt mempty++-- | @_capturesOpt mempty = _captures@+_capturesOpt :: Option -> Text -> Traversal' Text (NonEmpty Text)+_capturesOpt = withMatcher $ \matcher -> _capturesInternal matcher [0 ..]++-- | Given a pattern, produce an affine traversal (0 or 1 targets) that focuses+-- from a subject to the portion of it that matches.+--+-- Equivalent to @\\patt -> `_captures` patt . ix 0@, but more efficient.+_match :: Text -> Traversal' Text Text+_match = _matchOpt mempty++-- | @_matchOpt mempty = _match@+_matchOpt :: Option -> Text -> Traversal' Text Text+_matchOpt = withMatcher $ \matcher -> _capturesInternal matcher [0] . _headNE++-- * Support for Template Haskell compile-time regex analysis++-- | From options and pattern, determine parenthesized patterns\' names in+-- order.+predictCaptureNames :: Option -> Text -> IO [Maybe Text]+predictCaptureNames option patt = do+ code <- evalStateT+ (extractCompileEnv >>= extractCode patt)+ (applyOption option)++ withForeignPtr code getCaptureNames++-- | NOTE: The 0th capture is always named @Nothing@.+getCaptureNames :: Ptr Pcre2_code -> IO [Maybe Text]+getCaptureNames codePtr = do+ nameCount <- getCodeInfo @CUInt codePtr pcre2_INFO_NAMECOUNT+ nameEntrySize <- getCodeInfo @CUInt codePtr pcre2_INFO_NAMEENTRYSIZE+ nameTable <- getCodeInfo @PCRE2_SPTR codePtr pcre2_INFO_NAMETABLE++ -- Can't do [0 .. nameCount - 1] because it underflows when nameCount == 0+ let indexes = takeWhile (< nameCount) [0 ..]+ names <- fmap IM.fromList $ forM indexes $ \i -> do+ let entryPtr = nameTable `advancePtr` fromIntegral (i * nameEntrySize)+ groupNamePtr = entryPtr `advancePtr` 1+ groupNumber <- peek entryPtr+ groupNameLen <- lengthArray0 0 groupNamePtr+ groupName <- Text.fromPtr+ (castCUs groupNamePtr)+ (fromIntegral groupNameLen)+ return (fromIntegral groupNumber, groupName)++ hiCaptNum <- getCodeInfo @CUInt codePtr pcre2_INFO_CAPTURECOUNT++ return $ map (names IM.!?) [0 .. fromIntegral hiCaptNum]++-- | Low-level access to compiled pattern info, per the docs.+getCodeInfo :: (Storable a) => Ptr Pcre2_code -> CUInt -> IO a+getCodeInfo codePtr what = alloca $ \wherePtr -> do+ pcre2_pattern_info codePtr what wherePtr >>= check (== 0)+ peek wherePtr++-- | A wrapper around a list of captures that carries additional type-level+-- information about the number and names of those captures.+--+-- This type is only intended to be created by+-- `Text.Regex.Pcre2.regex`\/`Text.Regex.Pcre2._regex` and consumed by+-- `Text.Regex.Pcre2.capture`\/`Text.Regex.Pcre2._capture`, relying on type+-- inference. Specifying the @info@ explicitly in a type signature is not+-- supported—the definition of `CapturesInfo` is not part of the public+-- API and may change without warning.+--+-- After obtaining `Captures` it\'s recommended to immediately consume them and+-- transform them into application-level data, to avoid leaking the types to top+-- level and having to write signatures. In times of need, \"@Captures _@\" may+-- be written with the help of @{-\# LANGUAGE PartialTypeSignatures \#-}@.+newtype Captures (info :: CapturesInfo) = Captures (NonEmpty Text)++-- | The kind of `Captures`\'s @info@.+type CapturesInfo = (Nat, [(Symbol, Nat)])++-- | Look up the number of a capture at compile time, either by number or by+-- name. Throw a helpful 'TypeError' if the index doesn\'t exist.+type family CaptNum (i :: k) (info :: CapturesInfo) :: Nat where+ CaptNum (num :: Nat) '(hi, _) =+ If (CmpNat num 0 == 'LT || CmpNat num hi == 'GT)+ -- then+ (TypeError (TypeLits.Text "No capture numbered " :<>: ShowType num))+ -- else+ num++ CaptNum (name :: Symbol) '(_, '(name, num) ': _) = num+ CaptNum (name :: Symbol) '(hi, _ ': kvs) = 1 + CaptNum name '(hi, kvs)+ CaptNum (name :: Symbol) _ = TypeError+ (TypeLits.Text "No capture named " :<>: ShowType name)++ CaptNum _ _ = TypeError+ (TypeLits.Text "Capture index must be a number (Nat) or name (Symbol)")++-- | Safely lookup a capture in a `Captures` result obtained from a Template+-- Haskell-generated matching function.+--+-- The ugly type signature may be interpreted like this: /Given some capture/+-- /group index @i@ and some @info@ about a regex, ensure that index exists and/+-- /is resolved to the number @num@ at compile time. Then, at runtime, get a/+-- /capture group from a list of captures./+--+-- In practice the variable @i@ is specified by type application and the other+-- variables are inferred.+--+-- > capture @3+-- > capture @"bar"+--+-- Specifying a nonexistant number or name will result in a type error.+capture :: forall i info num. (CaptNum i info ~ num, KnownNat num) =>+ Captures info -> Text+capture = view $ _capture @i++-- | Like `capture` but focus from a `Captures` to a capture.+_capture :: forall i info num. (CaptNum i info ~ num, KnownNat num) =>+ Lens' (Captures info) Text+_capture f (Captures cs) =+ let (ls, c : rs) = NE.splitAt (fromInteger $ natVal @num Proxy) cs+ in f c <&> \c' -> Captures $ NE.fromList $ ls ++ c' : rs++-- * Exceptions++-- | The root of the PCRE2 exception hierarchy.+data SomePcre2Exception = forall e. (Exception e) => SomePcre2Exception e+instance Show SomePcre2Exception where+ show (SomePcre2Exception e) = show e+instance Exception SomePcre2Exception++-- | Vanilla PCRE2 exceptions with messages generated by the underlying C+-- library.+newtype Pcre2Exception = Pcre2Exception CInt+instance Show Pcre2Exception where+ show (Pcre2Exception x) = "pcre2: " ++ Text.unpack (getErrorMessage x)+instance Exception Pcre2Exception where+ toException = toException . SomePcre2Exception+ fromException = fromException >=> \(SomePcre2Exception e) -> cast e++-- | PCRE2 compile exceptions. Along with a message stating the cause, we show+-- the pattern with a cursor pointing at where the error is (if not after the+-- last character).+data Pcre2CompileException = Pcre2CompileException !CInt !Text !PCRE2_SIZE+instance Show Pcre2CompileException where+ show (Pcre2CompileException x patt offset) = intercalate "\n" $ [+ "pcre2_compile: " ++ Text.unpack (getErrorMessage x),+ replicate tab ' ' ++ Text.unpack patt] +++ [replicate (tab + offset') ' ' ++ "^" | offset' < Text.length patt]+ where+ tab = 20+ offset' = fromIntegral offset+instance Exception Pcre2CompileException where+ toException = toException . SomePcre2Exception+ fromException = fromException >=> \(SomePcre2Exception e) -> cast e++-- | Built-in message corresponding to the integer error code.+getErrorMessage :: CInt -> Text+getErrorMessage errorCode = unsafePerformIO $ do+ let bufCUs = 120+ allocaBytes (bufCUs * 2) $ \bufPtr -> do+ cus <- pcre2_get_error_message errorCode bufPtr (fromIntegral bufCUs)+ Text.fromPtr (castCUs bufPtr) (fromIntegral cus)++-- | Most PCRE2 C functions return an @int@ indicating a possible error. Test+-- it against a predicate, and throw an exception upon failure.+check :: (CInt -> Bool) -> CInt -> IO ()+check p x = unless (p x) $ throwIO $ Pcre2Exception x++-- * PCRE2 compile-time config++-- | Helper for getting PCRE2 compile-time config integers.+getConfigNumeric :: CUInt -> CUInt+getConfigNumeric what = unsafePerformIO $ alloca $ \ptr -> do+ pcre2_config what ptr+ peek ptr++-- | Helper for getting PCRE2 compile-time config strings.+getConfigString :: CUInt -> Maybe Text+getConfigString what = unsafePerformIO $ do+ len <- pcre2_config what nullPtr+ if len == pcre2_ERROR_BADOPTION+ then return Nothing+ -- FIXME Do we really need "+ 1" here?+ else allocaBytes (fromIntegral (len + 1) * 2) $ \ptr -> do+ pcre2_config what ptr+ Just <$> Text.fromPtr ptr (fromIntegral len - 1)++-- | See `Bsr`.+defaultBsr :: Bsr+defaultBsr = bsrFromC $ getConfigNumeric pcre2_CONFIG_BSR++-- | Which code widths PCRE2 is compiled to operate on. Can be any combination+-- of 8, 16, and 32. Should be @[16]@ but provided here for completeness.+compiledWidths :: [Int]+compiledWidths =+ let bitmap = getConfigNumeric pcre2_CONFIG_COMPILED_WIDTHS+ in [w | (b, w) <- [(1, 8), (2, 16), (4, 32)], b .&. bitmap /= 0]++-- | See `DepthLimit`.+defaultDepthLimit :: Int+defaultDepthLimit = fromIntegral $ getConfigNumeric pcre2_CONFIG_DEPTHLIMIT++-- | See `HeapLimit`.+defaultHeapLimit :: Int+defaultHeapLimit = fromIntegral $ getConfigNumeric pcre2_CONFIG_HEAPLIMIT++-- | Was PCRE2 built with JIT support?+supportsJit :: Bool+supportsJit = getConfigNumeric pcre2_CONFIG_JIT == 1++-- | A nice description of the CPU architecture JIT support is compiled for, if+-- any.+jitTarget :: Maybe Text+jitTarget = getConfigString pcre2_CONFIG_JITTARGET++-- | Number of bytes used for internal linkage in compiled regexes.+linkSize :: Int+linkSize = fromIntegral $ getConfigNumeric pcre2_CONFIG_LINKSIZE++-- | See `MatchLimit`.+defaultMatchLimit :: Int+defaultMatchLimit = fromIntegral $ getConfigNumeric pcre2_CONFIG_MATCHLIMIT++-- | See `Newline`.+defaultNewline :: Newline+defaultNewline = newlineFromC $ getConfigNumeric pcre2_CONFIG_NEWLINE++-- | See `NeverBackslashC`.+defaultIsNeverBackslashC :: Bool+defaultIsNeverBackslashC = getConfigNumeric pcre2_CONFIG_NEVER_BACKSLASH_C == 1++-- | See `ParensLimit`.+defaultParensLimit :: Int+defaultParensLimit = fromIntegral $ getConfigNumeric pcre2_CONFIG_PARENSLIMIT++-- | Size in bytes of PCRE2\'s built-in character processing tables.+defaultTablesLength :: Int+defaultTablesLength = fromIntegral $ getConfigNumeric pcre2_CONFIG_TABLES_LENGTH++-- | Unicode version string such as @8.0.0@, if Unicode is supported at all.+unicodeVersion :: Maybe Text+unicodeVersion = case getConfigString pcre2_CONFIG_UNICODE_VERSION of+ Just v | Text.unpack v == "Unicode not supported" -> Nothing+ maybeV -> maybeV++-- | Was PCRE2 built with Unicode support?+supportsUnicode :: Bool+supportsUnicode = getConfigNumeric pcre2_CONFIG_UNICODE == 1++-- | Version of the built-in C library. The versioning scheme is that PCRE+-- legacy is 8.x and PCRE2 is 10.x, so this should be @10.@/something/.+pcreVersion :: Text+pcreVersion = case getConfigString pcre2_CONFIG_VERSION of+ Just v -> v+ Nothing -> error "pcreVersion: unable to get string"
+ src/hs/Text/Regex/Pcre2/TH.hs view
@@ -0,0 +1,165 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Text.Regex.Pcre2.TH where++import Control.Applicative (Alternative(..))+import Data.IORef+import Data.Functor ((<&>))+import Data.List.NonEmpty (NonEmpty)+import qualified Data.List.NonEmpty as NE+import Data.Map.Lazy (Map)+import qualified Data.Map.Lazy as Map+import Data.Text (Text)+import qualified Data.Text as Text+import Language.Haskell.TH+import Language.Haskell.TH.Quote+import Language.Haskell.TH.Syntax+import System.IO.Unsafe (unsafePerformIO)+import Text.Regex.Pcre2.Internal++globalMatcherCache :: IORef (Map Text Matcher)+globalMatcherCache = unsafePerformIO $ newIORef Map.empty++memoMatcher :: Text -> Matcher+memoMatcher patt = unsafePerformIO $ do+ cache <- readIORef globalMatcherCache+ case Map.lookup patt cache of+ Just matcher -> return matcher+ Nothing -> do+ let matcher = unsafePerformIO $ assembleMatcher mempty patt+ atomicModifyIORef' globalMatcherCache $ \cache ->+ (Map.insert patt matcher cache, ())+ return matcher++matcherQ :: String -> ExpQ+matcherQ s = [e| memoMatcher $ Text.pack $(stringE s) |]++predictCaptureNamesQ :: String -> Q [Maybe Text]+predictCaptureNamesQ = runIO . predictCaptureNames mempty . Text.pack++toKVs :: [Maybe Text] -> [(Int, Text)]+toKVs names = [(number, name) | (number, Just name) <- zip [0 ..] names]++capturesInfoQ :: String -> Q (Maybe Type)+capturesInfoQ s = predictCaptureNamesQ s >>= \case+ -- No named captures, so need for Captures, so no info.+ [Nothing] -> return Nothing++ -- Named captures. Present+ -- [Nothing, Just "foo", Just "bar", Nothing]+ -- as+ -- '(3, '[ '("foo", 1), '("bar", 2)]).+ captureNames -> Just <$> promotedTupleT 2 `appT` hi `appT` kvs where+ -- 3+ hi = litT $ numTyLit $ fromIntegral $ length captureNames - 1+ -- '[ '("foo", 1), '("bar", 2)]+ kvs = foldr f promotedNilT $ toKVs captureNames where+ -- '("foo", 1) ': ...+ f (number, name) = appT $ appT promotedConsT $ -- ':+ promotedTupleT 2 -- '(,)+ `appT` litT (strTyLit $ Text.unpack name) -- "foo"+ `appT` litT (numTyLit $ fromIntegral number) -- 1++-- | /__As an expression__/+--+-- > regex :: (Alternative f) => String -> Text -> f (Captures info)+--+-- in the presence of parenthesized captures, or+--+-- > regex :: (Alternative f) => String -> Text -> f Text+--+-- if there are none. In other words, if there is more than the 0th capture,+-- this behaves like `capturesA` (except returning an opaque `Captures` instead+-- of a list), otherwise it behaves like `match`.+--+-- To retrieve an individual capture from a `Captures`, use `capture`.+--+-- > case [regex|(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})|] "submitted 2020-10-20" of+-- > Just cs ->+-- > let date = capture @0 cs+-- > year = read @Int $ Text.unpack $ capture @"y" cs+-- > ...+--+-- > forM_ ([regex|^\s+$|] line :: Maybe Text) $ \spaces ->+-- > error $ "line has spaces only: " ++ show spaces+--+-- /__As a pattern__/+--+-- This matches when the regex matches, whereupon any named captures are bound+-- to variables of the same names.+--+-- > case "submitted 2020-10-20" of+-- > [regex|(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})|] ->+-- > let year = read @Int $ Text.unpack y+-- > ...+--+-- Note that it is not possible to access the 0th capture this way. As a+-- workaround, explicitly capture the whole pattern and name it.+--+-- If there are no named captures, this simply acts as a guard.+regex :: QuasiQuoter+regex = QuasiQuoter {+ quoteExp = \s -> capturesInfoQ s >>= \case+ Nothing -> [e|+ let _cs = _capturesInternal $(matcherQ s) [0]+ in toAlternativeOf $ _cs . _headNE |]+ Just info -> [e|+ let wrap cs = Captures cs :: Captures $(return info)+ _cs = _capturesInternal $(matcherQ s) [0 ..]+ in toAlternativeOf $ _cs . to wrap |],++ quotePat = \s -> do+ captureNames <- predictCaptureNamesQ s++ case toKVs captureNames of+ -- No named captures. Test whether the string matches without+ -- creating any new Text values.+ [] -> viewP+ [e| has $ _capturesInternal $(matcherQ s) [] |]+ [p| True |]++ -- One or more named captures. Attempt to bind only those to local+ -- variables of the same names.+ numberedNames -> viewP e p where+ (nums, names) = unzip numberedNames+ e = [e|+ let _cs = _capturesInternal $(matcherQ s) $(liftData nums)+ in view $ _cs . to NE.toList |]+ p = listP $ map (varP . mkName . Text.unpack) names,++ quoteType = const $ fail "regex: cannot produce a type",++ quoteDec = const $ fail "regex: cannot produce declarations"}++-- | A lens variant of `regex`. Can only be used as an expression.+--+-- > _regex :: String -> Traversal' Text (Captures info)+-- > _regex :: String -> Traversal' Text Text+--+-- > import Control.Lens+-- > import Data.Text.Lens+-- >+-- > embeddedNumber :: Traversal' String Int+-- > embeddedNumber = packed . [_regex|\d+|] . unpacked . _Show+-- >+-- > main :: IO ()+-- > main = putStrLn $ "There are 14 competing standards" & embeddedNumber %~ (+ 1)+-- >+-- > -- There are 15 competing standards+--+_regex :: QuasiQuoter+_regex = QuasiQuoter {+ quoteExp = \s -> capturesInfoQ s >>= \case+ Nothing -> [e| _capturesInternal $(matcherQ s) [0] . _headNE |]+ Just info -> [e|+ let wrapped :: Lens' (NonEmpty Text) (Captures $(return info))+ wrapped f cs = f (Captures cs) <&> \(Captures cs') -> cs'+ in _capturesInternal $(matcherQ s) [0 ..] . wrapped |],++ quotePat = const $ fail "_regex: cannot produce a pattern",++ quoteType = const $ fail "_regex: cannot produce a type",++ quoteDec = const $ fail "_regex: cannot produce declarations"}
+ test/Spec.hs view
@@ -0,0 +1,220 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}++module Main where++import Control.Applicative (Alternative)+import Control.Exception (catch, evaluate, handle)+import Control.Monad.RWS.Lazy (ask, evalRWS, forM_, tell, void)+import Data.IORef+import Data.List.NonEmpty (NonEmpty(..))+import Data.Text (Text)+import qualified Data.Text as Text+import Lens.Micro.Platform+import Test.Hspec+import Text.Regex.Pcre2++main :: IO ()+main = hspec $ do+ let submitted = "submitted 2020-10-20"++ describe "partial application" $ do+ it "only causes one compilation" $ do+ onlyCausesOneCompilation $ \option ->+ matchesOpt option "foo"++ it "only causes one compilation (point-free expression)" $ do+ onlyCausesOneCompilation $ \option ->+ (||) <$> Text.null <*> matchesOpt option "foo"++ describe "basic matching" $ do+ -- verifies that NotEmpty makes a difference, see below+ it "matches an empty pattern to an empty subject" $ do+ match "" "" `shouldBe` Just ""++ it "works using matches" $ do+ matches "(?i)foo" "FOO" `shouldBe` True++ it "works using capturesA" $ do+ case capturesA "(\\d{4})-(\\d{2})-(\\d{2})" submitted of+ Just ne -> ne `shouldBe` "2020-10-20" :| ["2020", "10", "20"]+ Nothing -> expectationFailure "didn't match"++ describe "lens-powered matching" $ do+ let _nee :: Traversal' Text Text+ _nee = _match "(?i)\\bnee\\b"+ promptNee = traverseOf (_nee . unpacked) $ \s -> tell [s] >> ask++ it "can accrete effects while performing replacements" $ do+ let result = evalRWS+ (promptNee "We are the knights who say...NEE!")+ "NOO"+ undefined+ result `shouldBe` ("We are the knights who say...NOO!", ["NEE"])++ it "signals match failure by not targeting anything" $ do+ let result = evalRWS+ (promptNee "Shhhhh")+ undefined+ undefined+ result `shouldBe` ("Shhhhh", [])++ it "does not substitute when setting equal Text" $ do+ let threeAndMiddle = _captures ". (.) ."+ ("A A A" & threeAndMiddle .~ "A A A" :| ["B"]) `shouldBe` "A B A"+ ("A A A" & threeAndMiddle .~ "A B A" :| ["A"]) `shouldBe` "A B A"++ describe "option handling" $ do+ it "includes compile options" $ do+ matchOpt Ungreedy "a+" "aaa" `shouldBe` Just "a"++ it "includes extra compile options" $ do+ matchOpt BadEscapeIsLiteral "\\j" "\\j" `shouldBe` Just "j"++ it "includes compile context options" $ do+ let otherBsr+ | defaultBsr == BsrUnicode = BsrAnyCrlf+ | otherwise = BsrUnicode+ lineSep = "\x2028"+ matches "\\R" lineSep+ `shouldNotBe` matchesOpt (Bsr otherBsr) "\\R" lineSep++ -- We already know it includes compile recursion guards++ it "includes match options" $ do+ matchOpt NotEmpty "" "" `shouldBe` Nothing++ it "includes callouts" $ do+ calloutRanRef <- newIORef 0+ let callout = UnsafeCallout $ \_ -> do+ modifyIORef calloutRanRef (+ 1)+ return CalloutProceed+ matchOpt callout "(?C'foo')a(?C42)a" "aa" `shouldBe` Just "aa"+ readIORef calloutRanRef `shouldReturn` 2++ it "includes substitution callouts" $ do+ subCalloutRanRef <- newIORef 0+ let subCallout = UnsafeSubCallout $ \_ -> do+ modifyIORef subCalloutRanRef (+ 1)+ return SubCalloutAccept+ subOpt (subCallout <> SubGlobal) "a" "b" "aa" `shouldBe` "bb"+ readIORef subCalloutRanRef `shouldReturn` 2++ it "includes match context options" $ do+ matchOpt (OffsetLimit 10) "b" "aaaaaaaaaaab" `shouldBe` Nothing++ describe "user errors" $ do+ it "are thrown at match time" $ do+ (broken @Maybe "foo" `seq` return ())+ `shouldThrow` anyPcre2Exception++ it "are catchable using Control.Exception.evaluate" $ do+ let example = evaluate (broken "foo") `catch`+ \(_ :: SomePcre2Exception) -> return Nothing+ example `shouldReturn` Nothing++ it "are catchable using instance Alternative IO" $ do+ let example = broken "foo" `catch`+ \(_ :: SomePcre2Exception) -> return "broken"+ example `shouldReturn` "broken"++ describe "native substitution" $ do+ it "works using sub" $ do+ let result = sub+ "(\\w+) calling the (\\w+)"+ "$2 calling the $1"+ "the pot calling the kettle black"+ result `shouldBe` "the kettle calling the pot black"++ it "works using gsub" $ do+ gsub "a" "o" "apples and bananas" `shouldBe` "opples ond bononos"++ describe "regex :: QuasiQuoter" $ do+ context "as an expression" $ do+ it "works with parenthesized captures" $ do+ case [regex|(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})|] submitted of+ Nothing -> expectationFailure "regex didn't match"+ Just cs -> do+ let date = capture @0 cs+ year = read @Int $ Text.unpack $ capture @"y" cs+ (date, year) `shouldBe` ("2020-10-20", 2020)++ it "works without parenthesized captures" $ do+ let example = forM_ @Maybe ([regex|^\s+$|] " ") $ \spaces ->+ error $ "line has spaces only: " ++ show spaces+ example `shouldThrow` anyErrorCall++ context "as a pattern" $ do+ it "works with named captures" $ do+ case submitted of+ [regex|(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})|] -> do+ let year = read @Int $ Text.unpack y+ year `shouldBe` 2020+ _ -> expectationFailure "regex didn't match"++ it "works without named captures" $ do+ case "abc" of+ [regex|a(b)c|] -> return ()+ _ -> expectationFailure "regex didn't match"++ describe "_regex" $ do+ it "works with parenthesized captures" $ do+ -- Adapt the _captures example for use here+ let result = "Well bust my buttons!" &~ do+ zoom [_regex|(\w+) my (\w+)|] $ do+ _capture @1 . _head .= 'd'+ _capture @2 %= Text.reverse+ _last .= '?'+ result `shouldBe` "Well dust my snottub?"++ it "works without parenthesized captures" $ do+ let embeddedNumber :: Traversal' String Int+ embeddedNumber = packed . [_regex|\d+|] . unpacked . _Show+ result = "There are 14 competing standards"+ & embeddedNumber %~ (+ 1)+ result `shouldBe` "There are 15 competing standards"++ describe "an unset capture" $ do+ it "is treated as empty" $ do+ captures "(a)?" "" `shouldBe` ["", ""]++ it "is unchanged via Traversal'" $ do+ ("" & [_regex|(a)?|] . _capture @1 .~ "foo") `shouldBe` ""++ it "permits other captures to be changed via Traversal'" $ do+ ("" & [_regex|(a)?|] . _capture @0 .~ "foo") `shouldBe` "foo"++onlyCausesOneCompilation :: (Option -> Text -> a) -> Expectation+onlyCausesOneCompilation regexWithOpt = do+ counter <- newIORef (0 :: Int)+ let option = UnsafeCompileRecGuard $ \_ -> do+ modifyIORef counter (+ 1)+ return True+ run = void . evaluate . regexWithOpt option+ getCount = readIORef counter++ run "foo"+ countAfterOnce <- getCount+ countAfterOnce `shouldSatisfy` (> 0) -- probably 2!++ run "bar"+ run "baz"+ countAfterTwiceMore <- getCount+ countAfterTwiceMore `shouldBe` countAfterOnce++anyPcre2Exception :: Selector SomePcre2Exception+anyPcre2Exception _ = True++broken :: (Alternative f) => Text -> f Text+broken = match "*"++-- microlens doesn't have this yet as of 12/5/2020+_Show :: (Read a, Show a) => Traversal' String a+_Show f s = case reads s of+ [(x, "")] -> show <$> f x+ _ -> pure s