mirror of https://github.com/qt/qtbase.git
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts:
src/corelib/tools/qvector.h
Make QVector(DataPointer dd) public to be able to properly merge
5b4b437b30
from 5.15 into dev.
src/widgets/kernel/qapplication.cpp
tests/auto/tools/moc/allmocs_baseline_in.json
Done-With: Christian Ehrlicher <ch.ehrlicher@gmx.de>
Change-Id: I929ba7c036d570382d0454c2c75f6f0d96ddbc01
This commit is contained in:
commit
a503bf5470
File diff suppressed because it is too large
Load Diff
|
@ -1,913 +0,0 @@
|
|||
QT LICENSE AGREEMENT
|
||||
Agreement version 4.0
|
||||
|
||||
This License Agreement ("Agreement") is a legal agreement between The Qt
|
||||
Company (as defined below) and the Licensee (as defined below) for the license
|
||||
of Licensed Software (as defined below). Capitalized terms used herein are
|
||||
defined in Section 1.
|
||||
|
||||
WHEREAS:
|
||||
|
||||
(A). Licensee wishes to use the Licensed Software for the purpose of developing
|
||||
and distributing Applications and/or Devices; and
|
||||
|
||||
(B). The Qt Company is willing to grant the Licensee a right to use Licensed
|
||||
Software for such purpose pursuant to term and conditions of this Agreement.
|
||||
|
||||
NOW, THEREFORE, THE PARTIES HEREBY AGREE AS FOLLOWS:
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Affiliate" of a Party shall mean an entity (i) which is directly or indirectly
|
||||
controlling such Party; (ii) which is under the same direct or indirect
|
||||
ownership or control as such Party; or (iii) which is directly or indirectly
|
||||
owned or controlled by such Party. For these purposes, an entity shall be
|
||||
treated as being controlled by another if that other entity has fifty percent
|
||||
(50 %) or more of the votes in such entity, is able to direct its affairs
|
||||
and/or to control the composition of its board of directors or equivalent body.
|
||||
|
||||
"Applications" shall mean Licensee's software products created using the
|
||||
Licensed Software, which may include the Redistributables, or part
|
||||
thereof.
|
||||
|
||||
"Contractor(s)" shall mean third party consultants, distributors and
|
||||
contractors performing services to a Party under applicable contractual
|
||||
arrangement.
|
||||
|
||||
"Customer(s)" shall mean Licensee's end users to whom Licensee, directly or
|
||||
indirectly, distributes copies of the Redistributables.
|
||||
|
||||
"Deployment Platforms" shall mean operating systems specified in the License
|
||||
Certificate, in which the Redistributables can be distributed pursuant to the
|
||||
terms and conditions of this Agreement.
|
||||
|
||||
"Designated User(s)" shall mean the employee(s) of Licensee or Licensee's
|
||||
Affiliates acting within the scope of their employment or Licensee's
|
||||
Contractors acting within the scope of their services for Licensee and on
|
||||
behalf of Licensee. Designated Users shall be named in the License Certificate.
|
||||
|
||||
"Development License" shall mean the license needed by the Licensee for each
|
||||
Designated User to use the Licensed Software under the license grant described
|
||||
in Section 3.1 of this Agreement.
|
||||
|
||||
"Development Platforms" shall mean those operating systems specified in the
|
||||
License Certificate, in which the Licensed Software can be used under the
|
||||
Development License, but not distributed in any form or used for any other
|
||||
purpose.
|
||||
|
||||
"Devices" shall mean hardware devices or products that 1) are manufactured
|
||||
and/or distributed by the Licensee or its Affiliates or Contractors, and
|
||||
(2)(i) incorporate or integrate the Redistributables or parts thereof; or (ii)
|
||||
do not incorporate or integrate the Redistributables at the time of
|
||||
distribution, but where, when used by a Customer, the main user interface or
|
||||
substantial functionality of such device is provided by Application(s) or
|
||||
otherwise depends on the Licensed Software.
|
||||
|
||||
"Distribution License(s)" shall mean the license required for distribution of
|
||||
Redistributables in connection with Devices pursuant to license grant described
|
||||
in Section 3.3 of this Agreement.
|
||||
|
||||
"Distribution License Packs" shall mean set of prepaid Distribution Licenses
|
||||
for distribution of Redistributables, as defined in The Qt Company's standard
|
||||
price list, quote, Purchase Order confirmation or in an appendix hereto,
|
||||
as the case may be.
|
||||
|
||||
"Intellectual Property Rights" shall mean patents (including utility models),
|
||||
design patents, and designs (whether or not capable of registration), chip
|
||||
topography rights and other like protection, copyrights, trademarks, service
|
||||
marks, trade names, logos or other words or symbols and any other form of
|
||||
statutory protection of any kind and applications for any of the foregoing as
|
||||
well as any trade secrets.
|
||||
|
||||
"License Certificate" shall mean a certificate generated by The Qt Company for
|
||||
each Designated User respectively upon them downloading the licensed Software.
|
||||
License Certificate will be available under respective Designated User's Qt
|
||||
Account at account.qt.io and it will specify the Designated User, the
|
||||
Development Platforms, Deployment Platforms and the License Term. The terms of
|
||||
the License Certificate are considered part of this Agreement and shall be
|
||||
updated from time to time to reflect any agreed changes to the foregoing terms
|
||||
relating to Designated User's rights to the Licensed Software.
|
||||
|
||||
"License Fee" shall mean the fee charged to the Licensee for rights granted
|
||||
under the terms of this Agreement.
|
||||
|
||||
"License Term" shall mean the agreed validity period of the Development
|
||||
License of the respective Designated User, during which time the
|
||||
Designated User is entitled to use the Licensed Software, as set forth in the
|
||||
respective License Certificate.
|
||||
|
||||
"Licensed Software" shall mean all versions of the
|
||||
|
||||
(i) Qt Toolkit (including Qt Essentials, Qt Add-Ons and Value-Add modules) as
|
||||
described in http://doc.qt.io/qt-5/qtmodules.html,
|
||||
|
||||
(ii) Qt Creator (including Creator IDE tool) as described in
|
||||
http://doc.qt.io/qtcreator/index.html,
|
||||
|
||||
(iii) Qt 3D Studio as described in http://doc.qt.io/qt3dstudio/index.html, and
|
||||
|
||||
as well as corresponding online or electronic documentation, associated media
|
||||
and printed materials, including the source code, example programs and the
|
||||
documentation, licensed to the Licensee under this Agreement. Licensed Software
|
||||
does not include Third Party Software (as defined in Section 4), Open Source
|
||||
Qt, or other software products of The Qt Company (for example Qt Safe Renderer
|
||||
and Qt for Automation), unless such other software products of The Qt Company
|
||||
are separately agreed in writing to be included in scope of the Licensed
|
||||
Software.
|
||||
|
||||
"Licensee" shall mean the individual or legal entity that is party to this
|
||||
Agreement, as identified on the signature page hereof.
|
||||
|
||||
"Licensee's Records" shall mean books and records that are likely to contain
|
||||
information bearing on Licensee's compliance with this Agreement or the
|
||||
payments due to The Qt Company under this Agreement, including, but not limited
|
||||
to: assembly logs, sales records and distribution records.
|
||||
|
||||
"Modified Software" shall have the meaning as set forth in Section 2.3.
|
||||
|
||||
"Online Services" shall mean any services or access to systems made available
|
||||
by The Qt Company to the Licensee over the Internet relating to the Licensed
|
||||
Software or for the purpose of use by the Licensee of the Licensed Software or
|
||||
Support. Use of any such Online Services is discretionary for the Licensee and
|
||||
some of them may be subject to additional fees.
|
||||
|
||||
"Open Source Qt" shall mean the non-commercial Qt computer software products,
|
||||
licensed under the terms of the GNU Lesser General Public License, version
|
||||
2.1 or later ("LGPL") or the GNU General Public License, version 2.0 or later
|
||||
("GPL"). For clarity, Open Source Qt shall not be provided nor governed under
|
||||
this Agreement.
|
||||
|
||||
"Party" or "Parties" shall mean Licensee and/or The Qt Company.
|
||||
|
||||
"Redistributables" shall mean the portions of the Licensed Software set forth
|
||||
in Appendix 1, Section 1 that may be distributed pursuant to the terms of this
|
||||
Agreement in object code form only, including any relevant documentation.
|
||||
Where relevant, any reference to Licensed Software in this Agreement shall
|
||||
include and refer also to Redistributables.
|
||||
|
||||
"Renewal Term" shall mean an extension of previous License Term as agreed
|
||||
between the Parties.
|
||||
|
||||
"Submitted Modified Software" shall have the meaning as set forth in
|
||||
Section 2.3.
|
||||
|
||||
"Support" shall mean standard developer support that is provided by The Qt
|
||||
Company to assist Designated Users in using the Licensed Software in
|
||||
accordance with The Qt Company's standard support terms and as further
|
||||
defined in Section 8 hereunder.
|
||||
|
||||
"Taxes" shall have the meaning set forth in Section 10.5.
|
||||
|
||||
"Term" shall have the meaning set forth in Section 12.
|
||||
|
||||
"The Qt Company" shall mean:
|
||||
|
||||
(i) in the event Licensee is an individual residing in the United States or a
|
||||
legal entity incorporated in the United States or having its headquarters in
|
||||
the United States, The Qt Company Inc., a Delaware corporation with its office
|
||||
at 2350 Mission College Blvd., Suite 1020, Santa Clara, CA 95054, USA.; or
|
||||
|
||||
(ii) in the event the Licensee is an individual residing outside of the United
|
||||
States or a legal entity incorporated outside of the United States or having
|
||||
its registered office outside of the United States, The Qt Company Ltd., a
|
||||
Finnish company with its registered office at Bertel Jungin aukio D3A, 02600
|
||||
Espoo, Finland.
|
||||
|
||||
"Third Party Software " shall have the meaning set forth in Section 4.
|
||||
|
||||
"Updates" shall mean a release or version of the Licensed Software containing
|
||||
bug fixes, error corrections and other changes that are generally made
|
||||
available to users of the Licensed Software that have contracted for Support.
|
||||
Updates are generally depicted as a change to the digits following the decimal
|
||||
in the Licensed Software version number. The Qt Company shall make Updates
|
||||
available to the Licensee under the Support. Updates shall be considered as
|
||||
part of the Licensed Software hereunder.
|
||||
|
||||
"Upgrades" shall mean a release or version of the Licensed Software containing
|
||||
enhancements and new features and are generally depicted as a change to the
|
||||
first digit of the Licensed Software version number. In the event Upgrades are
|
||||
provided to the Licensee under this Agreement, they shall be considered as
|
||||
part of the Licensed Software hereunder.
|
||||
|
||||
2. OWNERSHIP
|
||||
|
||||
2.1 Ownership of The Qt Company
|
||||
|
||||
The Licensed Software is protected by copyright laws and international
|
||||
copyright treaties, as well as other intellectual property laws and treaties.
|
||||
The Licensed Software is licensed, not sold.
|
||||
|
||||
All The Qt Company's Intellectual Property Rights are and shall remain the
|
||||
exclusive property of The Qt Company or its licensors respectively.
|
||||
|
||||
2.2 Ownership of Licensee
|
||||
|
||||
All the Licensee's Intellectual Property Rights are and shall remain the
|
||||
exclusive property of the Licensee or its licensors respectively.
|
||||
|
||||
All Intellectual Property Rights to the Modified Software, Applications and
|
||||
Devices shall remain with the Licensee and no rights thereto shall be granted
|
||||
by the Licensee to The Qt Company under this Agreement (except as set forth in
|
||||
Section 2.3 below).
|
||||
|
||||
2.3 Modified Software
|
||||
|
||||
Licensee may create bug-fixes, error corrections, patches or modifications to
|
||||
the Licensed Software ("Modified Software"). Such Modified Software may break
|
||||
the source or binary compatibility with the Licensed Software (including
|
||||
without limitation through changing the application programming interfaces
|
||||
("API") or by adding, changing or deleting any variable, method, or class
|
||||
signature in the Licensed Software and/or any inter-process protocols, services
|
||||
or standards in the Licensed Software libraries). To the extent that Licensee's
|
||||
Modified Software so breaks source or binary compatibility with the Licensed
|
||||
Software, Licensee acknowledges that The Qt Company's ability to provide
|
||||
Support may be prevented or limited and Licensee's ability to make use of
|
||||
Updates may be restricted.
|
||||
|
||||
Licensee may, at its sole and absolute discretion, choose to submit Modified
|
||||
Software to The Qt Company ("Submitted Modified Software") in connection with
|
||||
Licensee's Support request, service request or otherwise. In the event Licensee
|
||||
does so, then, Licensee hereby grants The Qt Company a sublicensable,
|
||||
assignable, irrevocable, perpetual, worldwide, non-exclusive, royalty-free and
|
||||
fully paid-up license, under all of Licensee's Intellectual Property Rights, to
|
||||
reproduce, adapt, translate, modify, and prepare derivative works of, publicly
|
||||
display, publicly perform, sublicense, make available and distribute such
|
||||
Submitted Modified Software as The Qt Company sees fit at its free and absolute
|
||||
discretion.
|
||||
|
||||
3. LICENSES GRANTED
|
||||
|
||||
3.1 Development with Licensed Software
|
||||
|
||||
Subject to the terms of this Agreement, The Qt Company grants to Licensee a
|
||||
personal, worldwide, non-exclusive, non-transferable license, valid for the
|
||||
License Term, to use, modify and copy the Licensed Software by Designated Users
|
||||
on the Development Platforms for the sole purposes of designing, developing,
|
||||
demonstrating and testing Application(s) and/or Devices, and to provide thereto
|
||||
related support and other related services to end-user Customers.
|
||||
|
||||
Licensee may install copies of the Licensed Software on an unlimited number of
|
||||
computers provided that (i) only the Designated Users may use the Licensed
|
||||
Software, and (ii) all Designated Users must have a valid Development License
|
||||
to use Licensed Software.
|
||||
|
||||
Licensee may at any time designate another Designated User to replace a then-
|
||||
current Designated User by notifying The Qt Company in writing, provided that
|
||||
any Designated User may be replaced only once during any six-month period.
|
||||
|
||||
Upon expiry of the initially agreed License Term, the respective License Terms
|
||||
shall be automatically extended to one or more Renewal Term(s), unless and
|
||||
until either Party notifies the other Party in writing that it does not wish to
|
||||
continue the License Term, such notification to be provided to the other Party
|
||||
no less than ninety (90) days before expiry of the respective License Term.
|
||||
Unless otherwise agreed between the Parties, Renewal Term shall be of equal
|
||||
length with the initial Term.
|
||||
|
||||
Any such Renewal Term shall be subject to License Fees agreed between the
|
||||
Parties or, if no advance agreement exists, subject to The Qt Company's
|
||||
standard pricing applicable at the commencement date of any such Renewal Term.
|
||||
|
||||
3.2 Distribution of Applications
|
||||
|
||||
Subject to the terms of this Agreement, The Qt Company grants to Licensee a
|
||||
personal, worldwide, non-exclusive, non-transferable, revocable (for cause
|
||||
pursuant to this Agreement) right and license, valid for the Term, to
|
||||
|
||||
(i) distribute, by itself or through its Contractors, Redistributables as
|
||||
installed, incorporated or integrated into Applications for execution on the
|
||||
Deployment Platforms, and
|
||||
|
||||
(ii) grant sublicenses to Redistributables, as distributed hereunder, for
|
||||
Customers solely for Customer's internal use and to the extent necessary in
|
||||
order for the Customers to use the Applications for their respective intended
|
||||
purposes.
|
||||
|
||||
Right to distribute the Redistributables as part of an Application as provided
|
||||
herein is not royalty-bearing but is conditional upon the Licensee having paid
|
||||
the agreed Development Licenses from The Qt Company before distributing any
|
||||
Redistributables to Customers.
|
||||
|
||||
3.3 Distribution of Devices
|
||||
|
||||
Subject to the terms of this Agreement, The Qt Company grants to Licensee a
|
||||
personal, worldwide, non-exclusive, non-transferable, revocable (for cause
|
||||
pursuant to this Agreement) right and license, valid for the Term, to
|
||||
|
||||
(i) distribute, by itself or through one or more tiers of Contractors,
|
||||
Redistributables as installed, incorporated or integrated, or intended to be
|
||||
installed, incorporated or integrated into Devices for execution on the
|
||||
Deployment Platforms, and
|
||||
|
||||
(ii) grant sublicenses to Redistributables, as distributed hereunder, for
|
||||
Customers solely for Customer's internal use and to the extent necessary in
|
||||
order for the Customers to use the Devices for their respective intended
|
||||
purposes.
|
||||
|
||||
Right to distribute the Redistributables with Devices as provided herein is
|
||||
conditional upon the Licensee having purchased and paid the appropriate amount
|
||||
of Development and Distribution Licenses from The Qt Company before
|
||||
distributing any Redistributables to Customers.
|
||||
|
||||
3.4 Further Requirements
|
||||
|
||||
The licenses granted above in this Section 3 by The Qt Company to Licensee are
|
||||
conditional and subject to Licensee's compliance with the following terms:
|
||||
|
||||
(i) Licensee shall not remove or alter any copyright, trademark or other
|
||||
proprietary rights notice contained in any portion of the Licensed Software;
|
||||
|
||||
(ii) Applications must add primary and substantial functionality to the
|
||||
Licensed Software;
|
||||
|
||||
(iii) Applications may not pass on functionality which in any way makes it
|
||||
possible for others to create software with the Licensed Software; provided
|
||||
however that Licensee may use the Licensed Software's scripting and QML ("Qt
|
||||
Quick") functionality solely in order to enable scripting, themes and styles
|
||||
that augment the functionality and appearance of the Application(s) without
|
||||
adding primary and substantial functionality to the Application(s);
|
||||
|
||||
(iv) Applications must not compete with the Licensed Software;
|
||||
|
||||
(v) Licensee shall not use The Qt Company's or any of its suppliers' names,
|
||||
logos, or trademarks to market Applications, except that Licensee may use
|
||||
"Built with Qt" logo to indicate that Application(s) was developed using the
|
||||
Licensed Software;
|
||||
|
||||
(vi) Licensee shall not distribute, sublicense or disclose source code of
|
||||
Licensed Software to any third party (provided however that Licensee may
|
||||
appoint employee(s) of Contractors as Designated Users to use Licensed
|
||||
Software pursuant to this Agreement). Such right may be available for the
|
||||
Licensee subject to a separate software development kit ("SDK") license
|
||||
agreement to be concluded with The Qt Company;
|
||||
|
||||
(vii) Licensee shall not grant the Customers a right to (i) make copies of the
|
||||
Redistributables except when and to the extent required to use the Applications
|
||||
and/or Devices for their intended purpose, (ii) modify the Redistributables or
|
||||
create derivative works thereof, (iii) decompile, disassemble or otherwise
|
||||
reverse engineer Redistributables, or (iv) redistribute any copy or portion of
|
||||
the Redistributables to any third party, except as part of the onward sale of
|
||||
the Device on which the Redistributables are installed;
|
||||
|
||||
(viii) Licensee shall not and shall cause that its Affiliates or Contractors
|
||||
shall not a) in any way combine, incorporate or integrate Licensed Software
|
||||
with, or use Licensed Software for creation of, any software created with or
|
||||
incorporating Open Source Qt, or b) incorporate or integrate Applications
|
||||
into a hardware device or product other than a Device, unless Licensee has
|
||||
received an advance written permission from The Qt Company to do so. Absent
|
||||
such written permission, any and all distribution by the Licensee during the
|
||||
Term of a hardware device or product a) which incorporate or integrate any
|
||||
part of Licensed Software or Open Source Qt; or b) where the main user
|
||||
interface or substantial functionality is provided by software build with
|
||||
Licensed Software or Open Source Qt or otherwise depends on the Licensed
|
||||
Software or Open Source Qt, shall be considered as a Device distribution under
|
||||
this Agreement and dependent on compliance thereof (including but not limited
|
||||
to obligation to pay applicable License Fees for such distribution);
|
||||
|
||||
(ix) Licensee shall cause all of its Affiliates and Contractors entitled to
|
||||
make use of the licenses granted under this Agreement, to be contractually
|
||||
bound to comply with the relevant terms of this Agreement and not to use the
|
||||
Licensed Software beyond the terms hereof and for any purposes other than
|
||||
operating within the scope of their services for Licensee. Licensee shall be
|
||||
responsible for any and all actions and omissions of its Affiliates and
|
||||
Contractors relating to the Licensed Software and use thereof (including but
|
||||
not limited to payment of all applicable License Fees);
|
||||
|
||||
(x) Except when and to the extent explicitly provided in this Section 3,
|
||||
Licensee shall not transfer, publish, disclose, display or otherwise make
|
||||
available the Licensed Software;
|
||||
|
||||
; and
|
||||
|
||||
(xi) Licensee shall not attempt or enlist a third party to conduct or attempt
|
||||
to conduct any of the above.
|
||||
|
||||
Above terms shall not be applicable if and to the extent they conflict with any
|
||||
mandatory provisions of any applicable laws.
|
||||
|
||||
Any use of Licensed Software beyond the provisions of this Agreement is
|
||||
strictly prohibited and requires an additional license from The Qt Company.
|
||||
|
||||
4. THIRD PARTY SOFTWARE
|
||||
|
||||
The Licensed Software may provide links to third party libraries or code
|
||||
(collectively "Third Party Software") to implement various functions. Third
|
||||
Party Software does not comprise part of the Licensed Software. In some cases,
|
||||
access to Third Party Software may be included in the Licensed Software. Such
|
||||
Third Party Software will be listed in the ".../src/3rdparty" source tree
|
||||
delivered with the Licensed Software or documented in the Licensed Software, as
|
||||
such may be amended from time to time. Licensee acknowledges that use or
|
||||
distribution of Third Party Software is in all respects subject to applicable
|
||||
license terms of applicable third party right holders.
|
||||
|
||||
5. PRE-RELEASE CODE
|
||||
|
||||
The Licensed Software may contain pre-release code and functionality marked or
|
||||
otherwise stated as "Technology Preview", "Alpha", "Beta" or similar
|
||||
designation. Such pre-release code may be present in order to provide
|
||||
experimental support for new platforms or preliminary versions of one or more
|
||||
new functionalities. The pre-release code may not be at the level of
|
||||
performance and compatibility of a final, generally available, product
|
||||
offering of the Licensed Software. The pre-release parts of the Licensed
|
||||
Software may not operate correctly, may contain errors and may be substantially
|
||||
modified by The Qt Company prior to the first commercial product release, if
|
||||
any. The Qt Company is under no obligation to make pre-release code
|
||||
commercially available, or provide any Support or Updates relating thereto. The
|
||||
Qt Company assumes no liability whatsoever regarding any pre-release code, but
|
||||
any use thereof is exclusively at Licensee's own risk and expense.
|
||||
|
||||
6. LIMITED WARRANTY AND WARRANTY DISCLAIMER
|
||||
|
||||
The Qt Company hereby represents and warrants that it has the power and
|
||||
authority to grant the rights and licenses granted to Licensee under this
|
||||
Agreement.
|
||||
|
||||
Except as set forth above, the Licensed Software is licensed to Licensee
|
||||
"as is" and Licensee's exclusive remedy and The Qt Company's entire liability
|
||||
for errors in the Licensed Software shall be limited, at The Qt Company's
|
||||
option, to correction of the error, replacement of the Licensed Software or
|
||||
return of the applicable fees paid for the defective Licensed Software for the
|
||||
time period during which the License is not able to utilize the Licensed
|
||||
Software under the terms of this Agreement.
|
||||
|
||||
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE QT COMPANY ON BEHALF OF
|
||||
ITSELF AND ITS LICENSORS, SUPPLIERS AND AFFILIATES, DISCLAIMS ALL OTHER
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-
|
||||
INFRINGEMENT WITH REGARD TO THE LICENSED SOFTWARE. THE QT COMPANY DOES NOT
|
||||
WARRANT THAT THE LICENSED SOFTWARE WILL SATISFY LICENSEE'S REQUIREMENTS OR THAT
|
||||
IT WILL OPERATE WITHOUT DEFECT OR ERROR OR THAT THE OPERATION THEREOF WILL BE
|
||||
UNINTERRUPTED. ALL USE OF AND RELIANCE ON THE LICENSED SOFTWARE IS AT THE SOLE
|
||||
RISK OF AND RESPONSIBILITY OF LICENSEE.
|
||||
|
||||
7. INDEMNIFICATION AND LIMITATION OF LIABILITY
|
||||
|
||||
7.1 Limitation of Liability
|
||||
|
||||
EXCEPT FOR (I) CASES OF GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT, AND (II)
|
||||
BREACH OF CONFIDENTIALITY, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, IN NO
|
||||
EVENT SHALL EITHER PARTY BE LIABLE TO THE OTHER PARTY FOR ANY LOSS OF PROFIT,
|
||||
LOSS OF DATA, LOSS OF BUSINESS OR GOODWILL OR ANY OTHER INDIRECT, SPECIAL,
|
||||
CONSEQUENTIAL, INCIDENTAL OR PUNITIVE COST, DAMAGES OR EXPENSE OF ANY KIND,
|
||||
HOWSOEVER ARISING UNDER OR IN CONNECTION WITH THIS AGREEMENT. PARTIES
|
||||
SPECIFICALLY AGREE THAT LICENSEE'S OBLIGATION TO PAY LICENSE AND OTHER FEES
|
||||
CORRESPONDING TO ACTUAL USAGE OF LICENSED SOFTWARE HEREUNDER SHALL BE
|
||||
CONSIDERED AS A DIRECT DAMAGE.
|
||||
|
||||
EXCEPT FOR (I) CASES OF GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT, AND (II)
|
||||
BREACH OF CONFIDENTIALITY, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, IN
|
||||
NO EVENT SHALL EITHER PARTY'S TOTAL AGGREGATE LIABILITY UNDER THIS AGREEMENT
|
||||
EXCEED THE AGGREGATE LICENSE FEES PAID OR PAYABLE TO THE QT COMPANY FROM
|
||||
LICENSEE DURING THE PERIOD OF TWELVE (12) MONTHS IMMEDIATELY PRECEDING THE
|
||||
EVENT RESULTING IN SUCH LIABILITY.
|
||||
|
||||
THE PROVISIONS OF THIS SECTION 7 ALLOCATE THE RISKS UNDER THIS AGREEMENT
|
||||
BETWEEN THE QT COMPANY AND LICENSEE AND THE PARTIES HAVE RELIED UPON THE
|
||||
LIMITATIONS SET FORTH HEREIN IN DETERMINING WHETHER TO ENTER INTO THIS AGREEMENT.
|
||||
|
||||
7.2 Licensee's Indemnification
|
||||
|
||||
Licensee shall indemnify and hold harmless The Qt Company from and against any
|
||||
claim, injury, judgment, settlement, loss or expense, including attorneys' fees
|
||||
related to: (a) Licensee's misrepresentation in connection with The Qt Company
|
||||
or the Licensed Software or breach of this Agreement, (b) the Application or
|
||||
Device (except where such cause of liability is solely attributable to the
|
||||
Licensed Software).
|
||||
|
||||
8. SUPPORT, UPDATES AND ONLINE SERVICES
|
||||
|
||||
Upon due payment of the agreed License Fees the Licensee will be eligible to
|
||||
receive Support and Updates and to use the Online Services during the License
|
||||
Term, provided, however, that in the event the License Term is longer than 36
|
||||
months, Support is provided only for the first 12 months, unless the Parties
|
||||
specifically otherwise agree.
|
||||
|
||||
Unless otherwise decided by The Company at its free and absolute discretion,
|
||||
Upgrades will not be included in the Support but may be available subject to
|
||||
additional fees.
|
||||
|
||||
From time to time The Qt Company may change the Support terms, provided that
|
||||
during the respective ongoing License Term the level of Support provided by The
|
||||
Qt Company may not be reduced without the consent of the Licensee.
|
||||
|
||||
Unless otherwise agreed, The Qt Company shall not be responsible for providing
|
||||
any service or support to Customers.
|
||||
|
||||
9. CONFIDENTIALITY
|
||||
|
||||
Each Party acknowledges that during the Term of this Agreement each Party may
|
||||
receive information about the other Party's business, business methods,
|
||||
business plans, customers, business relations, technology, and other
|
||||
information, including the terms of this Agreement, that is confidential and
|
||||
of great value to the other Party, and the value of which would be
|
||||
significantly reduced if disclosed to third parties ("Confidential
|
||||
Information"). Accordingly, when a Party (the "Receiving Party") receives
|
||||
Confidential Information from the other Party (the "Disclosing Party"), the
|
||||
Receiving Party shall only disclose such information to employees and
|
||||
Contractors on a need to know basis, and shall cause its employees and
|
||||
employees of its Affiliates to: (i) maintain any and all Confidential
|
||||
Information in confidence; (ii) not disclose the Confidential Information to a
|
||||
third party without the Disclosing Party's prior written approval; and (iii)
|
||||
not, directly or indirectly, use the Confidential Information for any purpose
|
||||
other than for exercising its rights and fulfilling its responsibilities
|
||||
pursuant to this Agreement. Each Party shall take reasonable measures to
|
||||
protect the Confidential Information of the other Party, which measures shall
|
||||
not be less than the measures taken by such Party to protect its own
|
||||
confidential and proprietary information.
|
||||
|
||||
Obligation of confidentiality shall not apply to information that (i) is or
|
||||
becomes generally known to the public through no act or omission of the
|
||||
Receiving Party; (ii) was in the Receiving Party's lawful possession prior to
|
||||
the disclosure hereunder and was not subject to limitations on disclosure or
|
||||
use; (iii) is developed independently by employees or Contractors of the
|
||||
Receiving Party or other persons working for the Receiving Party who have not
|
||||
had access to the Confidential Information of the Disclosing Party, as proven
|
||||
by the written records of the Receiving Party; (iv) is lawfully disclosed to
|
||||
the Receiving Party without restrictions, by a third party not under an
|
||||
obligation of confidentiality; or (v) the Receiving Party is legally compelled
|
||||
to disclose, in which case the Receiving Party shall notify the Disclosing
|
||||
Party of such compelled disclosure and assert the privileged and confidential
|
||||
nature of the information and cooperate fully with the Disclosing Party to
|
||||
limit the scope of disclosure and the dissemination of disclosed Confidential
|
||||
Information to the minimum extent necessary.
|
||||
|
||||
The obligations under this Section 9 shall continue to remain in force for a
|
||||
period of five (5) years after the last disclosure, and, with respect to trade
|
||||
secrets, for so long as such trade secrets are protected under applicable trade
|
||||
secret laws.
|
||||
|
||||
10. FEES, DELIVERY AND PAYMENT
|
||||
|
||||
10.1 License Fees
|
||||
|
||||
License Fees are described in The Qt Company's standard price list, quote or
|
||||
Purchase Order confirmation or in an appendix hereto, as the case may be.
|
||||
|
||||
The License Fees shall not be refunded or claimed as a credit in any event or
|
||||
for any reason whatsoever.
|
||||
|
||||
10.2 Ordering Licenses
|
||||
|
||||
Licensee may purchase Development Licenses and Distribution Licenses pursuant
|
||||
to agreed pricing terms or, if no specific pricing terms have been agreed upon,
|
||||
at The Qt Company's standard pricing terms applicable at the time of purchase.
|
||||
|
||||
Licensee shall submit all purchase orders for Development Licenses and
|
||||
Distribution Licenses to The Qt Company by email or any other method acceptable
|
||||
to The Qt Company (each such order is referred to herein as a "Purchase Order")
|
||||
for confirmation, whereupon the Purchase Order shall become binding between the
|
||||
Parties.
|
||||
|
||||
10.3 Distribution License Packs
|
||||
|
||||
Unless otherwise agreed, Distribution Licenses shall be purchased by way of
|
||||
Distribution License Packs.
|
||||
|
||||
Upon due payment of the ordered Distribution License Pack(s), the Licensee will
|
||||
have an account of Distribution Licenses available for installing, bundling or
|
||||
integrating (all jointly "installing") the Redistributables with the Devices or
|
||||
for otherwise distributing the Redistributables in accordance with this
|
||||
Agreement.
|
||||
|
||||
Each time Licensee "installs" or distributes a copy of Redistributables, then
|
||||
one Distribution License is used, and Licensee's account of available
|
||||
Distribution Licenses is decreased accordingly.
|
||||
|
||||
Licensee may "install" copies of the Redistributables so long as Licensee has
|
||||
Distribution Licenses remaining on its account.
|
||||
|
||||
Redistributables will be deemed to have been "installed" into a Device when one
|
||||
of the following circumstances shall have occurred: a) the Redistributables
|
||||
have been loaded onto the Device and used outside of the Licensee's premises or
|
||||
b) the Device has been fully tested and placed into Licensee's inventory
|
||||
(or sold) for the first time (i.e., Licensee will not be required to use
|
||||
(or pay for) more than one Distribution License for each individual Device,
|
||||
e.g. in a situation where a Device is returned to Licensee's inventory after
|
||||
delivery to a distributor or sale to a Customer). In addition, if Licensee
|
||||
includes a back-up copy of the Redistributables on a CD-ROM or other storage
|
||||
medium along with the product, that backup copy of the Redistributables will
|
||||
not be deemed to have been "installed" and will not require an additional
|
||||
Distribution License.
|
||||
|
||||
10.4 Payment Terms
|
||||
|
||||
License Fees and any other charges under this Agreement shall be paid by
|
||||
Licensee no later than thirty (30) days from the date of the applicable invoice
|
||||
from The Qt Company.
|
||||
|
||||
The Qt Company will submit an invoice to Licensee after the date of this
|
||||
Agreement and/or after The Qt Company receives a Purchase Order from
|
||||
Licensee.
|
||||
|
||||
A late payment charge of the lower of (a) one percent per month; or (b) the
|
||||
interest rate stipulated by applicable law, shall be charged on any unpaid
|
||||
balances that remain past due.
|
||||
|
||||
The Qt Company shall have the right to suspend, terminate or withhold grants
|
||||
of all rights to the Licensed Software hereunder, including but not limited to
|
||||
the Developer License, Distribution License, and Support, should Licensee fail
|
||||
to make payment in timely fashion.
|
||||
|
||||
10.5 Taxes
|
||||
|
||||
All License Fees and other charges payable hereunder are gross amounts but
|
||||
exclusive of any value added tax, use tax, sales tax and other taxes, duties or
|
||||
tariffs ("Taxes"). Such applicable Taxes shall be paid by Licensee, or, where
|
||||
applicable, in lieu of payment of such Taxes, Licensee shall provide an
|
||||
exemption certificate to The Qt Company and any applicable authority.
|
||||
|
||||
11 RECORD-KEEPING AND REPORTING OBLIGATIONS; AUDIT RIGHTS
|
||||
|
||||
11.1 Licensee's Record-keeping
|
||||
|
||||
Licensee shall at all times maintain accurate and up-to-date written records of
|
||||
Licensee's activities related to the use of Licensed Software and distribution
|
||||
of Redistributables. The records shall be adequate to determine Licensee's
|
||||
compliance with the provisions of this Agreement and to demonstrate the number
|
||||
of Designated Users and Redistributables distributed by Licensee. The records
|
||||
shall conform to good accounting practices reasonably acceptable to The Qt
|
||||
Company.
|
||||
|
||||
Licensee shall, within thirty (30) days from receiving The Qt Company's request
|
||||
to that effect, deliver to The Qt Company a report on Licensee's usage of
|
||||
Licensed Software, such report to copies of Redistributables distributed by
|
||||
Licensee during that calendar quarter, and also detailing the number of
|
||||
undistributed copies of Redistributables made by Licensee and remaining in its
|
||||
account contain information, in sufficient detail, on (i) amount of users
|
||||
working with Licensed Software, (ii) copies of Redistributables distributed by
|
||||
Licensee during that calendar quarter, (iii) number of undistributed copies of
|
||||
Redistributables and corresponding number of unused Distribution Licenses
|
||||
remaining on Licensee's account, and (iv) any other information as The Qt
|
||||
Company may reasonably require from time to time.
|
||||
|
||||
11.2. The Qt Company's Audit Rights
|
||||
|
||||
The Qt Company or an independent auditor acting on behalf of The Qt Company's,
|
||||
may, upon at least five (5) business days' prior written notice and at its
|
||||
expense, audit Licensee with respect to the use of the Redistributables, but
|
||||
not more frequently than once during each 6-month period. Such audit may be
|
||||
conducted by mail, electronic means or through an in-person visit to Licensee's
|
||||
place of business. Any such in-person audit shall be conducted during regular
|
||||
business hours at Licensee's facilities and shall not unreasonably interfere
|
||||
with Licensee's business activities. The Qt Company or the independent auditor
|
||||
acting on behalf of The Qt Company shall be entitled to inspect Licensee's
|
||||
Records. All such Licensee's Records and use thereof shall be subject to an
|
||||
obligation of confidentiality under this Agreement.
|
||||
|
||||
If an audit reveals that Licensee is using the Licensed Software beyond scope
|
||||
of the licenses Licensee has paid for, Licensee agrees to immediately pay The
|
||||
Qt Company any amounts owed for such unauthorized use.
|
||||
|
||||
In addition, in the event the audit reveals a material violation of the terms
|
||||
of this Agreement (underpayment of more than 5% of License Fees shall always be
|
||||
deemed a material violation for purposes of this section), then the Licensee
|
||||
shall pay The Qt Company's reasonable cost of conducting such audit.
|
||||
|
||||
12 TERM AND TERMINATION
|
||||
|
||||
12.1 Term
|
||||
|
||||
This Agreement shall enter into force upon due acceptance by both Parties and
|
||||
remain in force for as long as there is any Development License(s) in force
|
||||
("Term"), unless and until terminated pursuant to the terms of this Section 12.
|
||||
|
||||
12.2 Termination by The Qt Company
|
||||
|
||||
The Qt Company shall have the right to terminate this Agreement upon thirty
|
||||
(30) days prior written notice if the Licensee is in material breach of any
|
||||
obligation of this Agreement and fails to remedy such breach within such notice
|
||||
period.
|
||||
|
||||
12.3 Mutual Right to Terminate
|
||||
|
||||
Either Party shall have the right to terminate this Agreement immediately upon
|
||||
written notice in the event that the other Party becomes insolvent, files for
|
||||
any form of bankruptcy, makes any assignment for the benefit of creditors, has
|
||||
a receiver, administrative receiver or officer appointed over the whole or a
|
||||
substantial part of its assets, ceases to conduct business, or an act
|
||||
equivalent to any of the above occurs under the laws of the jurisdiction of the
|
||||
other Party.
|
||||
|
||||
12.4 Parties' Rights and Duties upon Termination
|
||||
|
||||
Upon expiry or termination of the Agreement Licensee shall cease and shall
|
||||
cause all Designated Users (including those of its Affiliates' and
|
||||
Contractors') to cease using the Licensed Software and distribution of the
|
||||
Redistributables under this Agreement.
|
||||
|
||||
Notwithstanding the above, in the event the Agreement expires or is terminated:
|
||||
|
||||
(i) as a result of The Qt Company choosing not to renew the Development
|
||||
License(s) as set forth in Section 3.1, then all valid licenses possessed by
|
||||
the Licensee at such date shall be extended to be valid in perpetuity under the
|
||||
terms of this Agreement and Licensee is entitled to purchase additional
|
||||
licenses as set forth in Section 10.2; or
|
||||
|
||||
(ii) for reason other than by The Qt Company pursuant to item (i) above or
|
||||
pursuant to Section 12.2, then the Licensee is entitled, for a period of six
|
||||
(6) months after the effective date of termination, to continue distribution of
|
||||
Devices under the Distribution Licenses paid but unused at such effective date
|
||||
of termination.
|
||||
|
||||
Upon any such termination the Licensee shall destroy or return to The Qt
|
||||
Company all copies of the Licensed Software and all related materials and will
|
||||
certify the same to The Qt Company upon its request, provided however that
|
||||
Licensee may retain and exploit such copies of the Licensed Software as it may
|
||||
reasonably require in providing continued support to Customers.
|
||||
|
||||
Expiry or termination of this Agreement for any reason whatsoever shall not
|
||||
relieve Licensee of its obligation to pay any License Fees accrued or payable
|
||||
to The Qt Company prior to the effective date of termination, and Licensee
|
||||
shall immediately pay to The Qt Company all such fees upon the effective date
|
||||
of termination. Termination of this Agreement shall not affect any rights of
|
||||
Customers to continue use of Applications and Devices (and therein incorporated
|
||||
Redistributables).
|
||||
|
||||
12.5 Extension in case of bankruptcy
|
||||
|
||||
In the event The Qt Company is declared bankrupt under a final, non-cancellable
|
||||
decision by relevant court of law, and this Agreement is not, at the date of
|
||||
expiry of the Development License(s) pursuant to Section 3.1, assigned to
|
||||
party, who has assumed The Qt Company's position as a legitimate licensor of
|
||||
Licensed Software under this Agreement, then all valid licenses possessed by
|
||||
the Licensee at such date of expiry, and which the Licensee has not notified
|
||||
for expiry, shall be extended to be valid in perpetuity under the terms of
|
||||
this Agreement.
|
||||
|
||||
13. GOVERNING LAW AND LEGAL VENUE
|
||||
|
||||
In the event this Agreement is in the name of The Qt Company Inc., a Delaware
|
||||
Corporation, then:
|
||||
|
||||
(i) this Agreement shall be construed and interpreted in accordance with the
|
||||
laws of the State of California, USA, excluding its choice of law provisions;
|
||||
|
||||
(ii) the United Nations Convention on Contracts for the International Sale of
|
||||
Goods will not apply to this Agreement; and
|
||||
|
||||
(iii) any dispute, claim or controversy arising out of or relating to this
|
||||
Agreement or the breach, termination, enforcement, interpretation or validity
|
||||
thereof, including the determination of the scope or applicability of this
|
||||
Agreement to arbitrate, shall be determined by arbitration in San Francisco,
|
||||
USA, before one arbitrator. The arbitration shall be administered by JAMS
|
||||
pursuant to JAMS' Streamlined Arbitration Rules and Procedures. Judgment on the
|
||||
Award may be entered in any court having jurisdiction. This Section shall not
|
||||
preclude parties from seeking provisional remedies in aid of arbitration from a
|
||||
court of appropriate jurisdiction.
|
||||
|
||||
In the event this Agreement is in the name of The Qt Company Ltd., a Finnish
|
||||
Company, then:
|
||||
|
||||
(i) this Agreement shall be construed and interpreted in accordance with the
|
||||
laws of Finland, excluding its choice of law provisions;
|
||||
|
||||
(ii) the United Nations Convention on Contracts for the International Sale of
|
||||
Goods will not apply to this Agreement; and
|
||||
|
||||
(iii) any disputes, controversy or claim arising out of or relating to this
|
||||
Agreement, or the breach, termination or validity thereof shall be shall be
|
||||
finally settled by arbitration in accordance with the Arbitration Rules of
|
||||
Finland Chamber of Commerce. The arbitration tribunal shall consist of one (1),
|
||||
or if either Party so requires, of three (3), arbitrators. The award shall be
|
||||
final and binding and enforceable in any court of competent jurisdiction. The
|
||||
arbitration shall be held in Helsinki, Finland and the process shall be
|
||||
conducted in the English language. This Section shall not preclude parties from
|
||||
seeking provisional remedies in aid of arbitration from a court of appropriate
|
||||
jurisdiction.
|
||||
|
||||
14. GENERAL PROVISIONS
|
||||
|
||||
14.1 No Assignment
|
||||
|
||||
Except in the case of a merger or sale of substantially all of its corporate
|
||||
assets, Licensee shall not be entitled to assign or transfer all or any of its
|
||||
rights, benefits and obligations under this Agreement without the prior written
|
||||
consent of The Qt Company, which shall not be unreasonably withheld or delayed.
|
||||
The Qt Company shall be entitled to freely assign or transfer any of its
|
||||
rights, benefits or obligations under this Agreement.
|
||||
|
||||
14.2 No Third Party Representations
|
||||
|
||||
Licensee shall make no representations or warranties concerning the Licensed
|
||||
Software on behalf of The Qt Company. Any representation or warranty Licensee
|
||||
makes or purports to make on The Qt Company's behalf shall be void as to The
|
||||
Qt Company.
|
||||
|
||||
14.3 Surviving Sections
|
||||
|
||||
Any terms and conditions that by their nature or otherwise reasonably should
|
||||
survive termination of this Agreement shall so be deemed to survive.
|
||||
|
||||
14.4 Entire Agreement
|
||||
|
||||
This Agreement, the exhibits hereto, the License Certificate and any applicable
|
||||
Purchase Order constitute the complete agreement between the Parties and
|
||||
supersedes all prior or contemporaneous discussions, representations, and
|
||||
proposals, written or oral, with respect to the subject matters discussed
|
||||
herein.
|
||||
|
||||
In the event of any conflict or inconsistency between this Agreement and any
|
||||
Purchase Order, the terms of this Agreement will prevail over the terms of the
|
||||
Purchase Order with respect to such conflict or inconsistency.
|
||||
|
||||
Parties specifically acknowledge and agree that this Agreement prevails over
|
||||
any click-to-accept or similar agreements the Designated Users may need to
|
||||
accept online upon download of the Licensed Software, as may be required by
|
||||
The Qt Company's applicable processes relating to Licensed Software.
|
||||
|
||||
14.5 Modifications
|
||||
|
||||
No modification of this Agreement shall be effective unless contained in a
|
||||
writing executed by an authorized representative of each Party. No term or
|
||||
condition contained in Licensee's Purchase Order shall apply unless expressly
|
||||
accepted by The Qt Company in writing.
|
||||
|
||||
14.6 Force Majeure
|
||||
|
||||
Except for the payment obligations hereunder, neither Party shall be liable to
|
||||
the other for any delay or non-performance of its obligations hereunder in the
|
||||
event and to the extent that such delay or non-performance is due to an event
|
||||
of act of God, terrorist attack or other similar unforeseeable catastrophic
|
||||
event that prevents either Party for fulfilling its obligations under this
|
||||
Agreement and which such Party cannot avoid or circumvent ("Force Majeure
|
||||
Event"). If the Force Majeure Event results in a delay or non-performance of a
|
||||
Party for a period of three (3) months or longer, then either Party shall have
|
||||
the right to terminate this Agreement with immediate effect without any
|
||||
liability (except for the obligations of payment arising prior to the event of
|
||||
Force Majeure) towards the other Party.
|
||||
|
||||
14.7 Notices
|
||||
|
||||
Any notice given by one Party to the other shall be deemed properly given and
|
||||
deemed received if specifically acknowledged by the receiving Party in writing
|
||||
or when successfully delivered to the recipient by hand, fax, or special
|
||||
courier during normal business hours on a business day to the addresses
|
||||
specified for each Party on the signature page. Each communication and document
|
||||
made or delivered by one Party to the other Party pursuant to this Agreement
|
||||
shall be in the English language.
|
||||
|
||||
14.8 Export Control
|
||||
|
||||
Licensee acknowledges that the Redistributables may be subject to export
|
||||
control restrictions under the applicable laws of respective countries.
|
||||
Licensee shall fully comply with all applicable export license restrictions
|
||||
and requirements as well as with all laws and regulations relating to the
|
||||
Redistributables and exercise of licenses hereunder and shall procure all
|
||||
necessary governmental authorizations, including without limitation, all
|
||||
necessary licenses, approvals, permissions or consents, where necessary for the
|
||||
re-exportation of the Redistributables, Applications and/or Devices.
|
||||
|
||||
14.9 No Implied License
|
||||
|
||||
There are no implied licenses or other implied rights granted under this
|
||||
Agreement, and all rights, save for those expressly granted hereunder, shall
|
||||
remain with The Qt Company and its licensors. In addition, no licenses or
|
||||
immunities are granted to the combination of the Licensed Software with any
|
||||
other software or hardware not delivered by The Qt Company under this Agreement.
|
||||
|
||||
14.10 Attorney Fees
|
||||
|
||||
The prevailing Party in any action to enforce this Agreement shall be entitled
|
||||
to recover its attorney's fees and costs in connection with such action.
|
||||
|
||||
14.11 Severability
|
||||
|
||||
If any provision of this Agreement shall be adjudged by any court of competent
|
||||
jurisdiction to be unenforceable or invalid, that provision shall be limited or
|
||||
eliminated to the minimum extent necessary so that this Agreement shall
|
||||
otherwise remain in full force and effect and enforceable.
|
||||
|
||||
|
||||
IN WITNESS WHEREOF, the Parties hereto, intending to be legally bound hereby,
|
||||
have caused this Agreement to be executed by Licensee's authorized
|
||||
representative installing the Licensed Software and accepting the terms
|
||||
hereof in connection therewith.
|
||||
|
||||
|
||||
Appendix 1
|
||||
|
||||
1. Parts of the Licensed Software that are permitted for distribution in
|
||||
object code form only ("Redistributables") under this Agreement:
|
||||
|
||||
- The Licensed Software's Qt Essentials and Qt Add-on libraries
|
||||
- The Licensed Software's configuration tool ("qtconfig")
|
||||
- The Licensed Software's help tool ("Qt Assistant")
|
||||
- The Licensed Software's internationalization tools ("Qt Linguist", "lupdate",
|
||||
"lrelease")
|
||||
- The Licensed Software's QML ("Qt Quick") launcher tool ("qmlscene" or
|
||||
"qmlviewer")
|
||||
- The Licensed Software's installer framework
|
||||
|
||||
2. Parts of the Licensed Software that are not permitted for distribution
|
||||
include, but are not limited to:
|
||||
|
||||
- The Licensed Software's source code and header files
|
||||
- The Licensed Software's documentation
|
||||
- The Licensed Software's documentation generation tool ("qdoc")
|
||||
- The Licensed Software's tool for writing makefiles ("qmake")
|
||||
- The Licensed Software's Meta Object Compiler ("moc")
|
||||
- The Licensed Software's User Interface Compiler ("uic")
|
||||
- The Licensed Software's Resource Compiler ("rcc")
|
||||
- The Licensed Software's parts of the IDE tool ("Qt Creator")
|
||||
- The Licensed Software's parts of the Design tools ("Qt 3D Studio" or
|
||||
"Qt Quick Designer")
|
||||
- The Licensed Software's Emulator
|
|
@ -162,6 +162,8 @@ Build options:
|
|||
-reduce-exports ...... Reduce amount of exported symbols [auto]
|
||||
-reduce-relocations .. Reduce amount of relocations [auto] (Unix only)
|
||||
|
||||
-relocatable ......... Enable the Qt installation to be relocated [auto]
|
||||
|
||||
-plugin-manifests .... Embed manifests into plugins [no] (Windows only)
|
||||
-static-runtime ...... With -static, use static runtime [no] (Windows only)
|
||||
|
||||
|
|
|
@ -1480,6 +1480,10 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
|
|||
"type": "error",
|
||||
"condition": "!features.stl",
|
||||
"message": "Qt requires a compliant STL library."
|
||||
},
|
||||
{
|
||||
"type": "emccVersion",
|
||||
"condition": "config.wasm"
|
||||
}
|
||||
],
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ defineReplace(qtConfFunc_licenseCheck) {
|
|||
hasOpenSource = true
|
||||
else: \
|
||||
hasOpenSource = false
|
||||
exists($$QT_SOURCE_TREE/LICENSE.QT-LICENSE-AGREEMENT-4.0): \
|
||||
exists($$QT_SOURCE_TREE/LICENSE.QT-LICENSE-AGREEMENT): \
|
||||
hasCommercial = true
|
||||
else: \
|
||||
hasCommercial = false
|
||||
|
@ -224,7 +224,7 @@ defineReplace(qtConfFunc_licenseCheck) {
|
|||
affix = either
|
||||
}
|
||||
} else {
|
||||
theLicense = $$cat($$QT_SOURCE_TREE/LICENSE.QT-LICENSE-AGREEMENT-4.0, lines)
|
||||
theLicense = $$cat($$QT_SOURCE_TREE/LICENSE.QT-LICENSE-AGREEMENT, lines)
|
||||
theLicense = $$first(theLicense)
|
||||
showWhat = "Type '?' to view the $${theLicense}."
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ defineReplace(qtConfFunc_licenseCheck) {
|
|||
} else: equals(val, n)|equals(val, no) {
|
||||
return(false)
|
||||
} else: equals(commercial, yes):equals(val, ?) {
|
||||
licenseFile = $$QT_SOURCE_TREE/LICENSE.QT-LICENSE-AGREEMENT-4.0
|
||||
licenseFile = $$QT_SOURCE_TREE/LICENSE.QT-LICENSE-AGREEMENT
|
||||
} else: equals(commercial, no):equals(val, l) {
|
||||
licenseFile = $$QT_SOURCE_TREE/LICENSE.LGPL3
|
||||
} else: equals(commercial, no):equals(val, g):$$gpl2Ok {
|
||||
|
@ -823,6 +823,8 @@ defineTest(qtConfOutput_preparePaths) {
|
|||
libloc_absolute_path = $$absolute_path($$config.rel_input.libdir, $$config.input.prefix)
|
||||
}
|
||||
config.input.liblocation_to_prefix = $$relative_path($$config.input.prefix, $$libloc_absolute_path)
|
||||
config.qtbase.features.shared.available =
|
||||
export(config.qtbase.features.shared.available)
|
||||
|
||||
hostbindir_absolute_path = $$absolute_path($$config.rel_input.hostbindir, $$config.input.hostprefix)
|
||||
config.input.hostbindir_to_hostprefix = $$relative_path($$config.input.hostprefix, $$hostbindir_absolute_path)
|
||||
|
@ -1223,6 +1225,12 @@ defineReplace(qtConfOutputPostProcess_publicPro) {
|
|||
"QT_RELEASE_DATE = $$config.input.qt_release_date"
|
||||
}
|
||||
|
||||
wasm: {
|
||||
qt_emcc_version = $$qtSystemEmccVersion()
|
||||
output += \
|
||||
"QT_EMCC_VERSION = $$qt_emcc_version"
|
||||
}
|
||||
|
||||
return($$output)
|
||||
}
|
||||
|
||||
|
@ -1255,6 +1263,12 @@ defineReplace(qtConfOutputPostProcess_publicHeader) {
|
|||
!isEmpty(config.input.qt_libinfix): \
|
||||
output += "$${LITERAL_HASH}define QT_LIBINFIX \"$$eval(config.input.qt_libinfix)\""
|
||||
|
||||
wasm: {
|
||||
qt_emcc_version = $$qtSystemEmccVersion()
|
||||
output += \
|
||||
"$${LITERAL_HASH}define QT_EMCC_VERSION \"$$qt_emcc_version\""
|
||||
}
|
||||
|
||||
return($$output)
|
||||
}
|
||||
|
||||
|
@ -1337,6 +1351,14 @@ defineTest(qtConfReport_buildMode) {
|
|||
qtConfReportPadded($$1, $$build_mode)
|
||||
}
|
||||
|
||||
defineTest(qtConfReport_emccVersion) {
|
||||
EMCC_VERSION = $$qtSystemEmccVersion()
|
||||
REQ_VERSION = $$qtEmccRecommendedVersion()
|
||||
!equals(EMCC_VERSION, $$REQ_VERSION) {
|
||||
qtConfAddReport("You should use the recommended Emscripten version $$REQ_VERSION with this Qt. You have $$EMCC_VERSION $$QT_EMCC_VERSION")
|
||||
}
|
||||
}
|
||||
|
||||
# ensure pristine environment for configuration
|
||||
discard_from($$[QT_HOST_DATA/get]/mkspecs/qconfig.pri)
|
||||
discard_from($$[QT_HOST_DATA/get]/mkspecs/qmodule.pri)
|
||||
|
|
|
@ -0,0 +1,542 @@
|
|||
Qt 5.14 introduces many new features and improvements as well as bugfixes
|
||||
over the 5.13.x series. For more details, refer to the online documentation
|
||||
included in this distribution. The documentation is also available online:
|
||||
|
||||
https://doc.qt.io/qt-5/index.html
|
||||
|
||||
The Qt version 5.14 series is binary compatible with the 5.13.x series.
|
||||
Applications compiled for 5.13 will continue to run with 5.14.
|
||||
|
||||
Some of the changes listed in this file include issue tracking numbers
|
||||
corresponding to tasks in the Qt Bug Tracker:
|
||||
|
||||
https://bugreports.qt.io/
|
||||
|
||||
Each of these identifiers can be entered in the bug tracker to obtain more
|
||||
information about a particular change.
|
||||
|
||||
****************************************************************************
|
||||
* Important Behavioral Change *
|
||||
****************************************************************************
|
||||
|
||||
- [QTBUG-47644] WrapWord now correctly prefers line breaks between words
|
||||
in Korean text. WrapAnywhere can still be used to get breaks between
|
||||
syllables instead.
|
||||
|
||||
****************************************************************************
|
||||
* Potentially Source-Incompatible Changes *
|
||||
****************************************************************************
|
||||
|
||||
- qstringlist.h no longer includes qregexp.h.
|
||||
- Prefixing Q_NAMESPACE with an export macro may no longer work. Use the
|
||||
new Q_NAMESPACE_EXPORT macro for that use case.
|
||||
|
||||
****************************************************************************
|
||||
* QtCore *
|
||||
****************************************************************************
|
||||
|
||||
- Added support of deduction guides for QPair
|
||||
- Added new Qt::SplitBehavior, for use as eventual replacement for
|
||||
QString::SplitBehavior.
|
||||
- Added the new Q_NAMESPACE_EXPORT macro. It can be used just like
|
||||
Q_NAMESPACE to add meta-object information to a namespace; however it
|
||||
also supports exporting of such information from shared libraries.
|
||||
- [QTBUG-15234] Qt installations on the host system can now be relocated,
|
||||
i.e. moved to other directories.
|
||||
|
||||
- JSON:
|
||||
* Added overloads of functions taking key strings as QStringView; in
|
||||
QJsonObject, QJsonValue and QJsonDocument.
|
||||
|
||||
- QAtomicInteger:
|
||||
* Added loadRelaxed() and storeRelaxed(), to be used as replacements of
|
||||
load() / store().
|
||||
|
||||
- QAtomicPointer:
|
||||
* Added loadRelaxed() and storeRelaxed(), to be used as replacements of
|
||||
load() / store().
|
||||
|
||||
- QBasicTimer:
|
||||
* QBasicTimer is now a move-only class. Copying is now deprecated and
|
||||
will be removed in Qt 6.
|
||||
* Added swap() member and free function.
|
||||
|
||||
- QByteArray::operator[]:
|
||||
* Detach immediately, instead of deferring until modification via
|
||||
the returned QByteRef.
|
||||
* Deprecate reliance on its implicit resizing behavior. Support for
|
||||
writing past the end of QByteArray shall be removed in a future
|
||||
version of Qt.
|
||||
|
||||
- QCalendar:
|
||||
* Added QCalendar to support diverse calendars, supported by
|
||||
implementing QCalendarBackend.
|
||||
* Added support for Julian and Milankovic calendars. These are enabled
|
||||
by default, except in bootstrap builds.
|
||||
* Added support for the Jalali (Persian or Solar Hijri) calendar,
|
||||
controlled by feature jalalicalendar.
|
||||
* Added support for the Islamic Civil calendar, controlled by feature
|
||||
islamiccivilcalendar, with locale data that can be shared with other
|
||||
implementations, controlled by feature hijricalendar.
|
||||
|
||||
- QChar:
|
||||
* Added FormFeed (FF) special character.
|
||||
|
||||
- QCollator:
|
||||
* Added support for QStringView.
|
||||
* The default QCollator now uses the system's collation locale, rather
|
||||
than the system locale itself.
|
||||
|
||||
- QDataStream:
|
||||
* Enumerations can now be serialized through QDataStream without the
|
||||
need of manually defining streaming operators.
|
||||
|
||||
- QDate:
|
||||
* [QTBUG-64485] Added startOfDay() and endOfDay() methods to provide a
|
||||
QDateTime at the start and end of a given date, taking account of any
|
||||
time skipped by transitions, e.g. a DST spring-forward, which can lead
|
||||
to a day starting at 01:00 or ending just before 23:00.
|
||||
* Allow choice of calendar in various operations, with Gregorian
|
||||
remaining the default.
|
||||
|
||||
- QDateTime:
|
||||
* Invalid datetimes are now treated as equal and less than all valid
|
||||
ones. They could previously be found equal to valid datetimes.
|
||||
|
||||
- QDir:
|
||||
* Remove Windows specific long path markers when handling file paths
|
||||
with native separators.
|
||||
|
||||
- QEasingCurve:
|
||||
* QEasingCurve now properly streams all the data needed to QDataStream.
|
||||
|
||||
- QFileInfo:
|
||||
* [QTBUG-75869] Introduced QFileInfo::isJunction() to detect NTFS Junctions
|
||||
on Windows.
|
||||
|
||||
- QHash:
|
||||
* Added range constructor.
|
||||
|
||||
- QJsonObject:
|
||||
* Added insert(), remove(), and take() overloads taking QLatin1String.
|
||||
|
||||
- QLatin1Char:
|
||||
* Comparison against char now works even in QT_NO_CAST_FROM_ASCII
|
||||
builds.
|
||||
|
||||
- QLatin1Literal:
|
||||
* The undocumented QLatin1Literal type alias for QLatin1String is now
|
||||
deprecated. Use QLatin1String instead.
|
||||
|
||||
- QLatin1String:
|
||||
* Added indexOf().
|
||||
* Added contains().
|
||||
* Added lastIndexOf().
|
||||
|
||||
- QLineF:
|
||||
* added QLineF::intersects() as a replacement for QLineF::intersect()
|
||||
|
||||
- QLinkedList:
|
||||
* Added range constructor.
|
||||
|
||||
- QList:
|
||||
* Added range constructor.
|
||||
|
||||
- QLocale:
|
||||
* The system locale now knows what to use for collation,
|
||||
QLocale::system().collation().
|
||||
* The NaN obtained when reading "nan" as a floating-point value is now
|
||||
quiet rather than signaling.
|
||||
* The system locale's UI languages list now includes, as for that of an
|
||||
ordinary locale, the results of adding likely sub-tags from each
|
||||
locale name, and of removing some, where this doesn't change which
|
||||
locale is specified. This gives searches for translation files a
|
||||
better chance of finding a suitable file.
|
||||
|
||||
- QMetaObject:
|
||||
* [QTBUG-38876] Some internal members of the QMetaObject class have
|
||||
changed types. Those members are not public API and thus should not
|
||||
cause source incompatibilities.
|
||||
|
||||
- QMultiHash:
|
||||
* Added range constructor.
|
||||
|
||||
- QMutex:
|
||||
* Added QRecursiveMutex as a replacement of QMutex(QMutex::Recursive).
|
||||
|
||||
- QPoint/QPointF:
|
||||
* Added transposed().
|
||||
|
||||
- QPointer:
|
||||
* Added a free swap function.
|
||||
|
||||
- QSet:
|
||||
* Added range constructor.
|
||||
|
||||
- QSharedPointer:
|
||||
* Overloads of qSharedPointerObjectCast have been added to work on
|
||||
std::shared_ptr.
|
||||
* The swap overload for QSharedPointer in the std namespace has been
|
||||
removed; a new overload has been added in the Qt namespace.
|
||||
|
||||
- QSize/QSizeF:
|
||||
* Added grownBy(QMargin(F))/shrunkBy(QMargin(F)).
|
||||
|
||||
- QString:
|
||||
* The behavior of operator[] to allow implicit resizing of the string
|
||||
has been deprecated, and will be removed in a future version of Qt.
|
||||
* QString::operator[] detaches immediately. Previously, the detach was
|
||||
delayed until a modification was made to the string through the
|
||||
returned QCharRef.
|
||||
* QString::arg(QString, ..., QString) can now be called with more than
|
||||
nine arguments, as well as with QStringViews.
|
||||
|
||||
- QString/QStringRef:
|
||||
* The split functions now optionally take Qt::SplitBehavior.
|
||||
|
||||
- QStringList:
|
||||
* Added range constructor.
|
||||
* Added QStringView overloads of join(), filter(), and
|
||||
replaceInStrings().
|
||||
|
||||
- QStringView:
|
||||
* Added indexOf().
|
||||
* Added contains().
|
||||
* Added lastIndexOf().
|
||||
* Deprecated the (undocumented) QStringViewLiteral macro. Just use u""
|
||||
or QStringView(u"") instead.
|
||||
|
||||
- QStringView/QLatin1String:
|
||||
* Added arg(), taking arbitrarily many strings.
|
||||
|
||||
- QTextStream:
|
||||
* The NaN obtained when reading "nan" as a floating-point value is now
|
||||
quiet rather than signaling.
|
||||
|
||||
- QTimeZone:
|
||||
* [QTBUG-75565] The TZDB back-end now recognizes the contents of /etc/TZ
|
||||
as a fall-back for $TZ (as used by uClibc).
|
||||
|
||||
- QVarLengthArray:
|
||||
* Added range constructor.
|
||||
* Added a qHash overload.
|
||||
|
||||
- QVariant:
|
||||
* Fixed a bug that caused isNull() to be true after downcasting a
|
||||
QObject* payload using convert().
|
||||
|
||||
- QVector:
|
||||
* Added range constructor.
|
||||
|
||||
- QWeakPointer:
|
||||
* The data() function has been deprecated.
|
||||
* A swap overload has been added.
|
||||
|
||||
- QtGlobal:
|
||||
* Add new macros QT_DEPRECATED_VERSION and QT_DEPRECATED_VERSION_X to
|
||||
conditionally display deprecation warnings
|
||||
* Added qExchange(), a drop-in for C++14's std::exchange()
|
||||
|
||||
- Windows:
|
||||
* QSysInfo::prettyProductName() now returns a version including the
|
||||
Windows 10 release id or Windows 7 build number respectively,
|
||||
resembling the version string displayed by the winver tool.
|
||||
|
||||
****************************************************************************
|
||||
* QtDBus *
|
||||
****************************************************************************
|
||||
|
||||
- QDBusAbstractInterface:
|
||||
* The call() and asyncCall() methods now accept more than eight QVariant
|
||||
arguments.
|
||||
|
||||
- QDBusObjectPath:
|
||||
* Added explicit cast operator to QVariant.
|
||||
|
||||
****************************************************************************
|
||||
* QtGui *
|
||||
****************************************************************************
|
||||
|
||||
- QColor:
|
||||
* Added QColorConstants, a namespace containing constexpr QColor
|
||||
instances.
|
||||
|
||||
- A QColorSpace class has been added, and color spaces are now parsed from
|
||||
PNG and JPEG images. No automatic color space conversion is done
|
||||
however, and applications must request it.
|
||||
- Added support for filtering Vulkan debug messages in QVulkanInstance.
|
||||
This is especially useful for processing or suppressing messages from
|
||||
the validation layers.
|
||||
- Obsolete constructors and accessors in QWheelEvent now have proper
|
||||
deprecation macros, and are no longer in use in any Qt modules.
|
||||
What is left is intended to be compatible with planned changes in Qt 6.
|
||||
|
||||
- QFont:
|
||||
* [QTBUG-77908] Fixed kerning error with certain fonts.
|
||||
* [QTBUG-76239] Fixed an issue where application fonts would be parsed
|
||||
multiple times, causing some unnecessary overhead when during
|
||||
application startup.
|
||||
* [QTBUG-46322] Resolving a font that just has a family set with
|
||||
families set will prepend the family to the families so that it is
|
||||
still the first preference for the font.
|
||||
|
||||
- QImage:
|
||||
* [QTBUG-42540], [QTBUG-68787] Loading of image files having a file
|
||||
name suffix for a different image file type has been
|
||||
fixed. QImageReader will now ask the suffix format handler to
|
||||
confirm the file contents (canRead()), and fall back to normal
|
||||
file content recognition on failure. This implies a slight
|
||||
behavior change in QImageReader::loopCount(), ::imageCount() and
|
||||
::nextImageDelay(): For an unreadable file with a recognized
|
||||
suffix, they would earlier return 0, while they now will
|
||||
return -1, i.e. error, as per the documentation.
|
||||
|
||||
- QPainter:
|
||||
* HighQualityAntialiasing and NonCosmeticDefaultPen are marked as
|
||||
deprecated and don't have an effect anymore
|
||||
|
||||
- QTextDocument:
|
||||
* [QTBUG-36152] CSS styling of table cell borders (styling <td> and <th>
|
||||
elements) is now supported during HTML import and export, including
|
||||
border-color, border-width and border-style. Setting the table's
|
||||
border-width to a value >= 1 and enabling border-collapse will now draw
|
||||
a simple, clean table grid (1px) with an outer border of the specified
|
||||
width and color. A manual test was added, which allows editing HTML
|
||||
with live preview.
|
||||
* [QTBUG-43589] Fixed incorrect rounding of widths of variable-width
|
||||
columns in tables, to avoid border drawing artifacts.
|
||||
* [QTBUG-78318] QTextFrameFormat margins, padding and borders are now
|
||||
scaled to device coordinates, and thus correctly sized on high-dpi
|
||||
displays and printers.
|
||||
* Markdown (CommonMark or GitHub dialect) is now a supported format for
|
||||
reading into and writing from QTextDocument, via the setMarkdown() and
|
||||
toMarkdown() functions. We do not guarantee that every markdown
|
||||
document can be re-written exactly as it was read; but that does work
|
||||
in many cases, and it's OK to report bugs about cases that don't work.
|
||||
|
||||
- Touch:
|
||||
* [QTBUG-77142] When a stationary touchpoint contains some "interesting"
|
||||
property change (pressure or velocity, so far), it is delivered normally.
|
||||
|
||||
****************************************************************************
|
||||
* QtNetwork *
|
||||
****************************************************************************
|
||||
|
||||
- QAuthenticator:
|
||||
* [QTBUG-4117] Add support for SPNEGO/Negotiate
|
||||
|
||||
- QHostInfo:
|
||||
* Added move contructor.
|
||||
|
||||
- QNetworkAccessManager:
|
||||
* [QTBUG-69477] Don't fail when FTP does not implement the HELP command.
|
||||
* Added setAutoDeleteReplies to QNetworkAccessManager to enable the
|
||||
AutoDeleteReplyOnFinishAttribute attribute for all QNetworkRequests
|
||||
that are passed to QNetworkAccessManager.
|
||||
|
||||
- QNetworkRequest:
|
||||
* Added the AutoDeleteReplyOnFinishAttribute attribute to
|
||||
QNetworkRequest, which makes QNetworkAccessManager delete the
|
||||
QNetworkReply after it has emitted the "finished" signal.
|
||||
* Add an ability to configure HTTP/2 protocol
|
||||
|
||||
- QSslKey:
|
||||
* Key data is cleared as soon as possible when move-assigning.
|
||||
|
||||
- QSslSocket:
|
||||
* [QTBUG-72016] Added runtime validation of the SSL private key when it
|
||||
is loaded through a file path.
|
||||
|
||||
****************************************************************************
|
||||
* QtSql *
|
||||
****************************************************************************
|
||||
|
||||
- QPSQL:
|
||||
* [QTBUG-79033][QTBUG-79064] added support for PostgreSQL 12
|
||||
|
||||
- QSqlite:
|
||||
* Updated to v3.30.1
|
||||
|
||||
- QSqlite2:
|
||||
* Marked QSQLITE2 plugin as obsolete - it will be removed with Qt6
|
||||
together with the QTDS plugin
|
||||
|
||||
****************************************************************************
|
||||
* QtTestLib *
|
||||
****************************************************************************
|
||||
|
||||
- Comparison of QImage, QPixmap now checks for the device pixel ratio.
|
||||
- It is now possible to perform static initialization before QApplication
|
||||
instantiation by implementing a initMain() function in the test class.
|
||||
|
||||
****************************************************************************
|
||||
* QtWidgets *
|
||||
****************************************************************************
|
||||
|
||||
- QActionGroup:
|
||||
* Added new exclusionPolicy property. Set it to ExclusiveOptional to
|
||||
allow unchecking the active checkable action in an exclusive group.
|
||||
|
||||
- QCalendarWidget:
|
||||
* Allow choice of calendar, with Gregorian remaining the default.
|
||||
|
||||
- QComboBox:
|
||||
* Two new signals textHighlighted() and textActivated() were added to
|
||||
replace highlighted()/activated() QString overloads.
|
||||
|
||||
- QDateTimeEdit:
|
||||
* Allow choice of calendar, with Gregorian remaining the default.
|
||||
|
||||
- QFileDialog:
|
||||
* The widgets-based dialog now remembers the selected files when
|
||||
navigating the history.
|
||||
|
||||
- QFormLayout:
|
||||
* Honor the vertical expanding state of a widget inside a QFormLayout.
|
||||
|
||||
- QGraphicsWidget:
|
||||
* Added QMarginsF overloads of setContentsMargins() and
|
||||
setWindowFrameMargins().
|
||||
|
||||
- QGroupBox:
|
||||
* [QTBUG-259389 Always disable children of a checkable, unchecked group
|
||||
box before showing.
|
||||
|
||||
- QLabel:
|
||||
* Markdown is now a supported textFormat for QLabel.
|
||||
|
||||
- QLayout:
|
||||
* Prevent clipping of group box titles on macOS (and similar styles that
|
||||
draw into layout margins)
|
||||
|
||||
- QLineEdit:
|
||||
* Behavior change: now the editingFinished signal is emitted only once
|
||||
after the line edit content was edited.
|
||||
* The getTextMargins() member function has been deprecated in favor of
|
||||
textMargins().
|
||||
|
||||
- QStyle:
|
||||
* Style sheets now only use the part of the stylesheet font that it
|
||||
knows about. The remaining will be resolved/inherited from the
|
||||
context.
|
||||
|
||||
- QTextBrowser:
|
||||
* Markdown is now a supported format. QTextBrowser::setSource() detects
|
||||
the common file extensions (.md, .mkd and .markdown). In case it
|
||||
cannot be detected that way, setSource() now takes an optional
|
||||
ResourceType enum argument so that the type can be overridden.
|
||||
QTextBrowser inherits all the QTextEdit features: if readOnly is set
|
||||
to false, the user can perform the editing operations that QTextEdit
|
||||
allows. If readOnly is set to true (the default), the user can click
|
||||
Markdown hyperlinks to emit the anchorClicked() signal, as with HTML.
|
||||
|
||||
- QTextEdit:
|
||||
* [QTBUG-75931] Added support for copy-pasting foreground brushes with
|
||||
textures within same document.
|
||||
* Markdown (CommonMark or GitHub dialect) is now a supported format,
|
||||
via the markdown property. GitHub dialect is the default, and supports
|
||||
all features such as hyperlinks, images, tables, lists, checklists, etc.
|
||||
* If the text was loaded from a Markdown document that contains checkboxes,
|
||||
the user can click on them to toggle the states. The cursor changes to
|
||||
PointingHandCursor when the mouse is hovering over a checkbox.
|
||||
|
||||
- QTreeView:
|
||||
* Don't emit clicked signal after a doubleClicked signal.
|
||||
|
||||
- QWidget:
|
||||
* The getContentsMargins() member function has been deprecated in favor
|
||||
of contentsMargins().
|
||||
|
||||
****************************************************************************
|
||||
* Platform Specific Changes *
|
||||
****************************************************************************
|
||||
|
||||
- Android
|
||||
* Fixed an issue where an application installation would be irrecoverably
|
||||
broken if power loss or a crash occurred during its first initialization
|
||||
run.
|
||||
* Make it easy to run Qt tests on Android. "$ make check" is all that's
|
||||
needed to run a test on an Android device.
|
||||
* Remove ant support from androiddeployqt
|
||||
* Introduce "make apk" target, an easy way to create an apk.
|
||||
* Android depends on NDK r20+
|
||||
* Android multi arch build in one go, needed to support the new .aab
|
||||
packaging format.
|
||||
* -android-abis configure script parameter useful to compile Qt only for a
|
||||
selected Android ABIs.
|
||||
* Instead of bundling QML resources in assets and extracting them on first
|
||||
start, Qt now creates an .rcc file and register it before invoking the
|
||||
main function.
|
||||
* Fixed regression that made it impossible for an application to use the
|
||||
tap-and-hold gesture.
|
||||
|
||||
- Linux:
|
||||
* Added a device spec for Raspberry Pi 4 (32-bit, V3D)
|
||||
* Added a device spec for 64-bit i.MX8 systems (Vivante graphics stack)
|
||||
|
||||
- MinGW:
|
||||
* [QTBUG-4155] Added a suffix to debug mode pkgconfig files.
|
||||
|
||||
- macOS:
|
||||
* The drawableSize of Metal layers is no longer updated automatically on
|
||||
window resize or screen change. Update the size manually in response to
|
||||
resizeEvent(), or at the start of each frame, as needed.
|
||||
|
||||
- Mir:
|
||||
* The Mir platform plugin has been removed: use the Wayland plugin when
|
||||
connecting to a Mir display server.
|
||||
|
||||
- Windows:
|
||||
* It is now possible to enable RTL mode by passing the option -platform
|
||||
windows:reverse.
|
||||
* [QTBUG-74748] Fixed a bug where it would be impossible to
|
||||
request different faces of a font family after a specific type face
|
||||
has been in use.
|
||||
|
||||
****************************************************************************
|
||||
* Third-Party Code *
|
||||
****************************************************************************
|
||||
- Upgraded bundled Freetype version to 2.10.1.
|
||||
- Build sqlite without SQLITE_OMIT_LOAD_EXTENSION
|
||||
- Qt Gui: Added md4c markdown parser to src/3rdparty/md4c (MIT licensed).
|
||||
- [QTBUG-79418] Updated double-conversion code to upstream version 3.1.5.
|
||||
- [QTBUG-79420] libjpeg-turbo was updated to version 2.0.3
|
||||
- [QTBUG-79418] Updated DNS public suffix list
|
||||
|
||||
****************************************************************************
|
||||
* Tools *
|
||||
****************************************************************************
|
||||
|
||||
- rcc:
|
||||
* Added -d option to generate a dependency file.
|
||||
* Added support for Python as output format.
|
||||
|
||||
****************************************************************************
|
||||
* configure *
|
||||
****************************************************************************
|
||||
|
||||
- Added the configure option -qtlibinfix-plugins to rename plugins
|
||||
according to QT_LIBINFIX. This option is off by default.
|
||||
|
||||
****************************************************************************
|
||||
* CMake *
|
||||
****************************************************************************
|
||||
|
||||
- [QTBUG-38913][QTBUG-76562] Added ability to auto-import non-qml plugins
|
||||
on CMake builds
|
||||
|
||||
****************************************************************************
|
||||
* qmake *
|
||||
****************************************************************************
|
||||
|
||||
- Installation targets do not ignore the exit code of QINSTALL and
|
||||
QINSTALL_PROGRAM anymore.
|
||||
- Introduced the variables LEX_DIR and YACC_DIR which determine the
|
||||
location of lex/yacc output. Fixed parallel execution of lex/yacc for
|
||||
debug_and_release builds.
|
||||
- The syntax 'LIBS += -frameworkFoo', or 'LIBS += "-framework Foo"' is no
|
||||
longer supported. Use the canonical 'LIBS += -framework Foo' instead.
|
||||
- Fixed precompiled headers for the Clang compiler.
|
||||
|
||||
- Android:
|
||||
* Remove gcc-style PCH directives from the android-clang mkspec.
|
|
@ -1,39 +1,41 @@
|
|||
macro.aacute.HTML = "á"
|
||||
macro.Aring.HTML = "Å"
|
||||
macro.aring.HTML = "å"
|
||||
macro.Auml.HTML = "Ä"
|
||||
macro.author = "\\b{Author:}"
|
||||
macro.BR.HTML = "<br />"
|
||||
macro.copyright.HTML = "©"
|
||||
macro.eacute.HTML = "é"
|
||||
macro.gui = "\\b"
|
||||
macro.HR.HTML = "<hr />"
|
||||
macro.iacute.HTML = "í"
|
||||
macro.key = "\\b"
|
||||
macro.macos = "macOS"
|
||||
macro.menu = "\\b"
|
||||
macro.oslash.HTML = "ø"
|
||||
macro.ouml.HTML = "ö"
|
||||
macro.nullptr = "\\c{nullptr}"
|
||||
macro.QA = "\\e{Qt Assistant}"
|
||||
macro.QD = "\\e{Qt Designer}"
|
||||
macro.QL = "\\e{Qt Linguist}"
|
||||
macro.QQV = "\\e{Qt QML Viewer}"
|
||||
macro.QtVersion = "$QT_VERSION"
|
||||
macro.QtVer = "$QT_VER"
|
||||
macro.param = "\\e"
|
||||
macro.raisedaster.HTML = "<sup>*</sup>"
|
||||
macro.rarrow.HTML = "→"
|
||||
macro.reg.HTML = "<sup>®</sup>"
|
||||
macro.return = "Returns"
|
||||
macro.starslash = "\\c{*/}"
|
||||
macro.begincomment = "\\c{/*}"
|
||||
macro.endcomment = "\\c{*/}"
|
||||
macro.uuml.HTML = "ü"
|
||||
macro.mdash.HTML = "—"
|
||||
macro.pi.HTML = "Π"
|
||||
macro.beginqdoc.HTML = "/*!"
|
||||
macro.endqdoc.HTML = "*/"
|
||||
macro.aacute.HTML = "á"
|
||||
macro.Aring.HTML = "Å"
|
||||
macro.aring.HTML = "å"
|
||||
macro.Auml.HTML = "Ä"
|
||||
macro.author = "\\b{Author:}"
|
||||
macro.BR.HTML = "<br />"
|
||||
macro.copyright.HTML = "©"
|
||||
macro.eacute.HTML = "é"
|
||||
macro.gui = "\\b"
|
||||
macro.HR.HTML = "<hr />"
|
||||
macro.iacute.HTML = "í"
|
||||
macro.key = "\\b"
|
||||
macro.macos = "macOS"
|
||||
macro.menu = "\\b"
|
||||
macro.oslash.HTML = "ø"
|
||||
macro.ouml.HTML = "ö"
|
||||
macro.nullptr = "\\c{nullptr}"
|
||||
macro.QA = "\\e{Qt Assistant}"
|
||||
macro.QD = "\\e{Qt Designer}"
|
||||
macro.QL = "\\e{Qt Linguist}"
|
||||
macro.QQV = "\\e{Qt QML Viewer}"
|
||||
macro.QtVersion = "$QT_VERSION"
|
||||
macro.QtVer = "$QT_VER"
|
||||
macro.param = "\\e"
|
||||
macro.raisedaster.HTML = "<sup>*</sup>"
|
||||
macro.raisedaster.DocBook = "\\sup{*}"
|
||||
macro.rarrow.HTML = "→"
|
||||
macro.reg.HTML = "<sup>®</sup>"
|
||||
macro.rego.DocBook = "\\sup{®}"
|
||||
macro.return = "Returns"
|
||||
macro.starslash = "\\c{*/}"
|
||||
macro.begincomment = "\\c{/*}"
|
||||
macro.endcomment = "\\c{*/}"
|
||||
macro.uuml.HTML = "ü"
|
||||
macro.mdash.HTML = "—"
|
||||
macro.pi.HTML = "Π"
|
||||
macro.beginqdoc.HTML = "/*!"
|
||||
macro.endqdoc.HTML = "*/"
|
||||
macro.borderedimage = "\\div {class=\"border\"} \\image \1\n\\enddiv"
|
||||
|
||||
macro.beginfloatleft.HTML = "<div style=\"float: left; margin-right: 2em\">"
|
||||
|
|
|
@ -95,7 +95,7 @@ QVariant MimetypeModel::data(const QModelIndex &index, int role) const
|
|||
if (role != Qt::DecorationRole || !index.isValid() || index.data(iconQueriedRole).toBool())
|
||||
return QStandardItemModel::data(index, role);
|
||||
QStandardItem *item = itemFromIndex(index);
|
||||
const QString iconName = item->data(mimeTypeRole).value<QMimeType>().iconName();
|
||||
const QString iconName = qvariant_cast<QMimeType>(item->data(mimeTypeRole)).iconName();
|
||||
if (!iconName.isEmpty())
|
||||
item->setIcon(QIcon::fromTheme(iconName));
|
||||
item->setData(QVariant(true), iconQueriedRole);
|
||||
|
@ -104,7 +104,7 @@ QVariant MimetypeModel::data(const QModelIndex &index, int role) const
|
|||
|
||||
QMimeType MimetypeModel::mimeType(const QModelIndex &index) const
|
||||
{
|
||||
return index.data(mimeTypeRole).value<QMimeType>();
|
||||
return qvariant_cast<QMimeType>(index.data(mimeTypeRole));
|
||||
}
|
||||
|
||||
void MimetypeModel::populate()
|
||||
|
|
|
@ -144,7 +144,7 @@ static QCborValue convertFromVariant(const QVariant &v, TrimFloatingPoint fpTrim
|
|||
}
|
||||
|
||||
if (v.userType() == qMetaTypeId<VariantOrderedMap>()) {
|
||||
const auto m = v.value<VariantOrderedMap>();
|
||||
const auto m = qvariant_cast<VariantOrderedMap>(v);
|
||||
QCborMap map;
|
||||
for (const auto &pair : m)
|
||||
map.insert(convertFromVariant(pair.first, fpTrimming),
|
||||
|
|
|
@ -98,7 +98,7 @@ static QString dumpVariant(const QVariant &v, const QString &indent = QLatin1Str
|
|||
int type = v.userType();
|
||||
if (type == qMetaTypeId<VariantOrderedMap>() || type == QVariant::Map) {
|
||||
const auto map = (type == QVariant::Map) ?
|
||||
VariantOrderedMap(v.toMap()) : v.value<VariantOrderedMap>();
|
||||
VariantOrderedMap(v.toMap()) : qvariant_cast<VariantOrderedMap>(v);
|
||||
|
||||
result = QLatin1String("Map {");
|
||||
for (const auto &pair : map) {
|
||||
|
|
|
@ -336,7 +336,7 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v)
|
|||
} else if (type == QVariant::Map || type == qMetaTypeId<VariantOrderedMap>()) {
|
||||
const VariantOrderedMap map = (type == QVariant::Map) ?
|
||||
VariantOrderedMap(v.toMap()) :
|
||||
v.value<VariantOrderedMap>();
|
||||
qvariant_cast<VariantOrderedMap>(v);
|
||||
|
||||
xml.writeStartElement("map");
|
||||
for (const auto &pair : map) {
|
||||
|
@ -425,10 +425,10 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v)
|
|||
default:
|
||||
if (type == qMetaTypeId<qfloat16>()) {
|
||||
xml.writeAttribute(typeString, "number");
|
||||
xml.writeCharacters(QString::number(float(v.value<qfloat16>())));
|
||||
xml.writeCharacters(QString::number(float(qvariant_cast<qfloat16>(v))));
|
||||
} else if (type == qMetaTypeId<QCborSimpleType>()) {
|
||||
xml.writeAttribute(typeString, "CBOR simple type");
|
||||
xml.writeCharacters(QString::number(int(v.value<QCborSimpleType>())));
|
||||
xml.writeCharacters(QString::number(int(qvariant_cast<QCborSimpleType>(v))));
|
||||
} else {
|
||||
// does this convert to string?
|
||||
const char *typeName = v.typeName();
|
||||
|
|
|
@ -74,7 +74,7 @@ int main(int argc, char *argv[])
|
|||
qDebug() << "Stored:" << stored;
|
||||
|
||||
//! [retrieving a custom value]
|
||||
Message retrieved = stored.value<Message>();
|
||||
Message retrieved = qvariant_cast<Message>(stored);
|
||||
qDebug() << "Retrieved:" << retrieved;
|
||||
retrieved = qvariant_cast<Message>(stored);
|
||||
qDebug() << "Retrieved:" << retrieved;
|
||||
|
|
|
@ -286,7 +286,7 @@ void RegularExpressionDialog::refresh()
|
|||
|
||||
setResultUiEnabled(true);
|
||||
|
||||
QRegularExpression::MatchType matchType = matchTypeComboBox->currentData().value<QRegularExpression::MatchType>();
|
||||
QRegularExpression::MatchType matchType = qvariant_cast<QRegularExpression::MatchType>(matchTypeComboBox->currentData());
|
||||
QRegularExpression::PatternOptions patternOptions = QRegularExpression::NoPatternOption;
|
||||
QRegularExpression::MatchOptions matchOptions = QRegularExpression::NoMatchOption;
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ void MainWindow::findStyles(const QFont &font)
|
|||
void MainWindow::filterChanged(int f)
|
||||
{
|
||||
const QFontComboBox::FontFilter filter =
|
||||
filterCombo->itemData(f).value<QFontComboBox::FontFilter>();
|
||||
qvariant_cast<QFontComboBox::FontFilter>(filterCombo->itemData(f));
|
||||
fontCombo->setFontFilters(filter);
|
||||
statusBar()->showMessage(tr("%n font(s) found", nullptr, fontCombo->count()));
|
||||
}
|
||||
|
|
|
@ -361,7 +361,7 @@ QWidget *MainWindow::createImagesGroupBox()
|
|||
QVBoxLayout *layout = new QVBoxLayout(imagesGroupBox);
|
||||
layout->addWidget(imagesTable);
|
||||
return imagesGroupBox;
|
||||
//! [25]
|
||||
//! [24]
|
||||
}
|
||||
|
||||
//! [26]
|
||||
|
|
|
@ -50,12 +50,15 @@
|
|||
|
||||
#include <QApplication>
|
||||
|
||||
#include "norwegianwoodstyle.h"
|
||||
#include "widgetgallery.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Q_INIT_RESOURCE(styles);
|
||||
|
||||
QApplication::setStyle(new NorwegianWoodStyle);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
WidgetGallery gallery;
|
||||
gallery.show();
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
NorwegianWoodStyle::NorwegianWoodStyle() :
|
||||
QProxyStyle(QStyleFactory::create("windows"))
|
||||
{
|
||||
setObjectName("NorwegianWood");
|
||||
}
|
||||
|
||||
//! [0]
|
||||
|
|
|
@ -143,6 +143,7 @@ WidgetGallery::WidgetGallery(QWidget *parent)
|
|||
setLayout(mainLayout);
|
||||
|
||||
setWindowTitle(tr("Styles"));
|
||||
styleChanged();
|
||||
}
|
||||
//! [4]
|
||||
|
||||
|
@ -150,12 +151,10 @@ WidgetGallery::WidgetGallery(QWidget *parent)
|
|||
void WidgetGallery::changeStyle(const QString &styleName)
|
||||
//! [5] //! [6]
|
||||
{
|
||||
if (styleName == "NorwegianWood") {
|
||||
if (styleName == "NorwegianWood")
|
||||
QApplication::setStyle(new NorwegianWoodStyle);
|
||||
} else {
|
||||
else
|
||||
QApplication::setStyle(QStyleFactory::create(styleName));
|
||||
}
|
||||
changePalette();
|
||||
}
|
||||
//! [6]
|
||||
|
||||
|
@ -170,6 +169,25 @@ void WidgetGallery::changePalette()
|
|||
}
|
||||
//! [8]
|
||||
|
||||
void WidgetGallery::changeEvent(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::StyleChange)
|
||||
styleChanged();
|
||||
}
|
||||
|
||||
void WidgetGallery::styleChanged()
|
||||
{
|
||||
auto styleName = QApplication::style()->objectName();
|
||||
for (int i = 0; i < styleComboBox->count(); ++i) {
|
||||
if (QString::compare(styleComboBox->itemText(i), styleName, Qt::CaseInsensitive) == 0) {
|
||||
styleComboBox->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
changePalette();
|
||||
}
|
||||
|
||||
//! [9]
|
||||
void WidgetGallery::advanceProgressBar()
|
||||
//! [9] //! [10]
|
||||
|
|
|
@ -80,8 +80,12 @@ class WidgetGallery : public QDialog
|
|||
public:
|
||||
WidgetGallery(QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *) override;
|
||||
|
||||
private slots:
|
||||
void changeStyle(const QString &styleName);
|
||||
void styleChanged();
|
||||
void changePalette();
|
||||
void advanceProgressBar();
|
||||
|
||||
|
|
|
@ -85,21 +85,21 @@ void MainWindow::setBrushColor()
|
|||
//! [2]
|
||||
void MainWindow::setAlphaValuator(QAction *action)
|
||||
{
|
||||
m_canvas->setAlphaChannelValuator(action->data().value<TabletCanvas::Valuator>());
|
||||
m_canvas->setAlphaChannelValuator(qvariant_cast<TabletCanvas::Valuator>(action->data()));
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
void MainWindow::setLineWidthValuator(QAction *action)
|
||||
{
|
||||
m_canvas->setLineWidthType(action->data().value<TabletCanvas::Valuator>());
|
||||
m_canvas->setLineWidthType(qvariant_cast<TabletCanvas::Valuator>(action->data()));
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
void MainWindow::setSaturationValuator(QAction *action)
|
||||
{
|
||||
m_canvas->setColorSaturationValuator(action->data().value<TabletCanvas::Valuator>());
|
||||
m_canvas->setColorSaturationValuator(qvariant_cast<TabletCanvas::Valuator>(action->data()));
|
||||
}
|
||||
//! [4]
|
||||
|
||||
|
|
|
@ -90,6 +90,6 @@ void LocaleSelector::emitLocaleSelected(int index)
|
|||
QVariant v = itemData(index);
|
||||
if (!v.isValid())
|
||||
return;
|
||||
const QLocale l = v.value<QLocale>();
|
||||
const QLocale l = qvariant_cast<QLocale>(v);
|
||||
emit localeSelected(l);
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ bool XbelTree::write(QIODevice *device) const
|
|||
|
||||
void XbelTree::updateDomElement(const QTreeWidgetItem *item, int column)
|
||||
{
|
||||
QDomElement element = item->data(0, DomElementRole).value<QDomElement>();
|
||||
QDomElement element = qvariant_cast<QDomElement>(item->data(0, DomElementRole));
|
||||
if (!element.isNull()) {
|
||||
if (column == 0) {
|
||||
QDomElement oldTitleElement = element.firstChildElement(titleElement());
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
include(qcc-base.conf)
|
||||
|
||||
isEmpty(QMAKE_WAYLAND_SCANNER): QMAKE_WAYLAND_SCANNER = $$(QNX_HOST)/usr/bin/wayland-scanner
|
||||
|
||||
QMAKE_PLATFORM = qnx $$QMAKE_PLATFORM
|
||||
|
||||
QMAKE_LFLAGS_SHLIB += -shared
|
||||
|
|
|
@ -7,4 +7,6 @@ CONFIG += bitcode reduce_exports shallow_bundle no_qt_rpath
|
|||
|
||||
INCLUDEPATH += $$PWD/uikit
|
||||
|
||||
DEFINES += GLES_SILENCE_DEPRECATION
|
||||
|
||||
include(mac.conf)
|
||||
|
|
|
@ -36,6 +36,7 @@ build_pass {
|
|||
}
|
||||
}
|
||||
} else: contains(TEMPLATE, "lib"):!static:!QTDIR_build:android_install {
|
||||
!contains(TARGET, "_$${QT_ARCH}"): TARGET = $${TARGET}_$${QT_ARCH}
|
||||
target.path = /libs/$$ANDROID_TARGET_ARCH/
|
||||
INSTALLS *= target
|
||||
}
|
||||
|
|
|
@ -63,11 +63,12 @@ contains(TEMPLATE, ".*app"):!build_pass:!android-embedded {
|
|||
QML_ROOT_PATH = $$_PRO_FILE_PWD_
|
||||
FILE_CONTENT += " \"qml-root-path\": $$emitString($$QML_ROOT_PATH),"
|
||||
FILE_CONTENT += " \"stdcpp-path\": $$emitString($$ANDROID_STDCPP_PATH),"
|
||||
!isEmpty(RESOURCES) {
|
||||
!isEmpty(RESOURCES)|!isEmpty(QMLCACHE_RESOURCE_FILES) {
|
||||
# Make sure that qmake generated qrc files are accounted for
|
||||
load(resources_functions)
|
||||
qtFlattenResources()
|
||||
for(resource, RESOURCES) {
|
||||
NEWRESOURCES = $$RESOURCES $$QMLCACHE_RESOURCE_FILES
|
||||
for(resource, NEWRESOURCES) {
|
||||
contains(resource, ".*\\qmake_qmake_immediate.qrc$") {
|
||||
# They will be created for each architecture, since they could be different
|
||||
# we need to account for all of them
|
||||
|
|
|
@ -35,6 +35,7 @@ moc_collect_json.output = $$MOC_COLLECT_JSON_OUTPUT
|
|||
moc_collect_json.name = Collect moc JSON output into central file
|
||||
|
||||
install_metatypes {
|
||||
do_install_metatypes.CONFIG += no_check_exist
|
||||
do_install_metatypes.path = $$[QT_INSTALL_LIBS]/metatypes
|
||||
do_install_metatypes.files = $$OUT_PWD/$$MOC_COLLECT_JSON_OUTPUT
|
||||
prefix_build {
|
||||
|
|
|
@ -666,6 +666,7 @@ defineTest(qtConfLibrary_inline) {
|
|||
vars += $$eval(config.commandline.rev_assignments.$${iv})
|
||||
defined(config.input.$${iv}, var) {
|
||||
eval($${1}.builds.$${b} = $$eval(config.input.$${iv}))
|
||||
export($${1}.builds.$${b})
|
||||
$${1}.builds._KEYS_ *= $${b}
|
||||
any = true
|
||||
} else {
|
||||
|
@ -680,11 +681,14 @@ defineTest(qtConfLibrary_inline) {
|
|||
export($${1}.builds._KEYS_)
|
||||
# we also reset the generic libs, to avoid surprises.
|
||||
$${1}.libs =
|
||||
export($${1}.libs)
|
||||
}
|
||||
|
||||
# direct libs. overwrites inline libs.
|
||||
defined(config.input.$${input}.libs, var): \
|
||||
defined(config.input.$${input}.libs, var) {
|
||||
eval($${1}.libs = $$eval(config.input.$${input}.libs))
|
||||
export($${1}.libs)
|
||||
}
|
||||
|
||||
includes = $$eval(config.input.$${input}.incdir)
|
||||
|
||||
|
@ -693,6 +697,7 @@ defineTest(qtConfLibrary_inline) {
|
|||
!isEmpty(prefix) {
|
||||
includes += $$prefix/include
|
||||
$${1}.libs = -L$$prefix/lib $$eval($${1}.libs)
|
||||
export($${1}.libs)
|
||||
}
|
||||
|
||||
libdir = $$eval(config.input.$${input}.libdir)
|
||||
|
|
|
@ -6,16 +6,6 @@ isEmpty(QMAKE_MOD_RCC):QMAKE_MOD_RCC = qrc
|
|||
!contains(QMAKE_RESOURCE_FLAGS, -root):!isEmpty(QMAKE_RESOURCE_ROOT):QMAKE_RESOURCE_FLAGS += -root $$QMAKE_RESOURCE_ROOT
|
||||
!contains(QMAKE_RESOURCE_FLAGS, -name): QMAKE_RESOURCE_FLAGS += -name ${QMAKE_FILE_BASE}
|
||||
|
||||
# http://www.w3.org/TR/xml/#syntax
|
||||
defineReplace(xml_escape) {
|
||||
1 ~= s,&,&,
|
||||
1 ~= s,\',',
|
||||
1 ~= s,\",",
|
||||
1 ~= s,<,<,
|
||||
1 ~= s,>,>,
|
||||
return($$1)
|
||||
}
|
||||
|
||||
load(resources_functions)
|
||||
qtFlattenResources()
|
||||
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
# http://www.w3.org/TR/xml/#syntax
|
||||
defineReplace(xml_escape) {
|
||||
1 ~= s,&,&,
|
||||
1 ~= s,\',',
|
||||
1 ~= s,\",",
|
||||
1 ~= s,<,<,
|
||||
1 ~= s,>,>,
|
||||
return($$1)
|
||||
}
|
||||
|
||||
defineTest(qtFlattenResources) {
|
||||
RESOURCES += qmake_immediate
|
||||
immediate = qmake_immediate$$QMAKE_RESOURCES_IMMEDIATE_NR
|
||||
defined(QMAKE_RESOURCES_IMMEDIATE_NR, var): \
|
||||
QMAKE_RESOURCES_IMMEDIATE_NR = $$num_add($$QMAKE_RESOURCES_IMMEDIATE_NR, 1)
|
||||
else: \
|
||||
QMAKE_RESOURCES_IMMEDIATE_NR = 1
|
||||
|
||||
RESOURCES += $$immediate
|
||||
for(resource, RESOURCES) {
|
||||
# Regular case of user qrc file
|
||||
contains(resource, ".*\\.qrc$"): \
|
||||
|
@ -7,10 +23,10 @@ defineTest(qtFlattenResources) {
|
|||
|
||||
# Fallback for stand-alone files/directories
|
||||
!defined($${resource}.files, var) {
|
||||
!equals(resource, qmake_immediate) {
|
||||
!equals(resource, $$immediate) {
|
||||
!exists($$absolute_path($$resource, $$_PRO_FILE_PWD_)): \
|
||||
warning("Failure to find: $$resource")
|
||||
qmake_immediate.files += $$resource
|
||||
$${immediate}.files += $$resource
|
||||
OTHER_FILES *= $$resource
|
||||
}
|
||||
RESOURCES -= $$resource
|
||||
|
@ -56,8 +72,9 @@ defineTest(qtFlattenResources) {
|
|||
RESOURCES -= $$resource
|
||||
RESOURCES += $$resource_file
|
||||
}
|
||||
export(QMAKE_RESOURCES_IMMEDIATE_NR)
|
||||
export(RESOURCES)
|
||||
export(OTHER_FILES)
|
||||
export(qmake_immediate.files)
|
||||
export($${immediate}.files)
|
||||
return(true)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
load(default_pre)
|
||||
load(emcc_ver)
|
|
@ -0,0 +1,23 @@
|
|||
defineReplace(qtEmccRecommendedVersion) {
|
||||
return (1.38.27)
|
||||
}
|
||||
|
||||
defineReplace(qtSystemEmccVersion) {
|
||||
E_VERSION = $$system("emcc -v 2>&1 | perl -alne $$shell_quote($_ = $F[9]; s/://; print;) ")
|
||||
return ($${E_VERSION})
|
||||
}
|
||||
|
||||
defineTest(qtConfTest_emccVersion) {
|
||||
|
||||
REQ_VERSION = $$qtEmccRecommendedVersion()
|
||||
EMCC_VERSION = $$qtSystemEmccVersion()
|
||||
|
||||
!defined(QT_EMCC_VERSION, var):!equals(EMCC_VERSION, $${REQ_VERSION}) {
|
||||
warning ("You should use the recommended Emscripten version $$REQ_VERSION with this Qt. You have $${EMCC_VERSION} ")
|
||||
}
|
||||
contains(TEMPLATE, .*app) {
|
||||
!equals(QT_EMCC_VERSION, $$EMCC_VERSION) {
|
||||
warning("This Qt was built with Emscripten version $${QT_EMCC_VERSION}. You have $${EMCC_VERSION}. The difference may cause issues.")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
|
||||
|
||||
# DESTDIR will be empty if not set in the app .pro file; make sure it has a value
|
||||
isEmpty(DESTDIR): DESTDIR = $$OUT_PWD
|
||||
|
||||
exists($$QMAKE_QT_CONFIG) {
|
||||
## this may be subject to change
|
||||
|
||||
qtConfig(thread) {
|
||||
|
||||
EMCC_THREAD_LFLAGS += -s USE_PTHREADS=1
|
||||
|
@ -109,6 +112,8 @@ contains(TEMPLATE, .*app) {
|
|||
}
|
||||
}
|
||||
|
||||
qtConfTest_emccVersion()
|
||||
|
||||
# Pass --source-map-base on the linker line. This informs the
|
||||
# browser where to find the source files when debugging.
|
||||
WASM_SOURCE_MAP_BASE = http://localhost:8000/
|
||||
|
|
|
@ -64,6 +64,8 @@
|
|||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
disableMainThreadChecker = "YES"
|
||||
enableGPUFrameCaptureMode = "3"
|
||||
enableGPUValidationMode = "1"
|
||||
debugDocumentVersioning = "NO"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable>
|
||||
|
|
|
@ -6,6 +6,7 @@ include(../common/gcc-base.conf)
|
|||
include(../common/clang.conf)
|
||||
|
||||
load(device_config)
|
||||
load(emcc_ver)
|
||||
|
||||
# Support setting WASM_OBJECT_FILES with -device-option WASM_OBJECT_FILES=1
|
||||
!isEmpty(WASM_OBJECT_FILES): {
|
||||
|
@ -15,7 +16,10 @@ load(device_config)
|
|||
QMAKE_CXXFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES
|
||||
QMAKE_LFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES
|
||||
} else {
|
||||
EMCC_COMMON_LFLAGS += -s \"BINARYEN_TRAP_MODE=\'clamp\'\"
|
||||
EMSCRIPTEN_VERSION=$$qtSystemEmccVersion()
|
||||
lessThan(EMSCRIPTEN_VERSION, 1.39) {
|
||||
EMCC_COMMON_LFLAGS += -s \"BINARYEN_TRAP_MODE=\'clamp\'\"
|
||||
}
|
||||
}
|
||||
|
||||
EMTERP_FLAGS = \
|
||||
|
|
|
@ -24,7 +24,8 @@ QOBJS = \
|
|||
qfile.o qfiledevice.o qfileinfo.o qfilesystemengine.o \
|
||||
qfilesystementry.o qfsfileengine.o qfsfileengine_iterator.o \
|
||||
qiodevice.o qsettings.o qtemporaryfile.o qtextstream.o \
|
||||
qcborvalue.o qjsoncbor.o qjsonarray.o qjsondocument.o qjsonobject.o qjsonparser.o qjsonvalue.o \
|
||||
qcborstreamwriter.o qcborvalue.o \
|
||||
qjsoncbor.o qjsonarray.o qjsondocument.o qjsonobject.o qjsonparser.o qjsonvalue.o \
|
||||
qmetatype.o qsystemerror.o qvariant.o \
|
||||
quuid.o \
|
||||
qarraydata.o qbitarray.o qbytearray.o qbytearraylist.o qbytearraymatcher.o \
|
||||
|
@ -96,6 +97,7 @@ DEPEND_SRC = \
|
|||
$(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qcborstreamwriter.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qcborvalue.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qdatastream.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qjsonarray.cpp \
|
||||
|
@ -135,6 +137,7 @@ DEPEND_SRC = \
|
|||
|
||||
CPPFLAGS = -g $(EXTRA_CPPFLAGS) \
|
||||
-I$(QMKSRC) -I$(QMKLIBSRC) -I$(QMKGENSRC) \
|
||||
-I$(SOURCE_PATH)/src/3rdparty/tinycbor/src \
|
||||
-I$(QMKGENSRC)/unix -I$(QMKGENSRC)/win32 -I$(QMKGENSRC)/mac \
|
||||
-I$(INC_PATH) -I$(INC_PATH)/QtCore \
|
||||
-I$(INC_PATH)/QtCore/$(QT_VERSION) -I$(INC_PATH)/QtCore/$(QT_VERSION)/QtCore \
|
||||
|
@ -463,6 +466,9 @@ qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp
|
|||
qdatastream.o: $(SOURCE_PATH)/src/corelib/serialization/qdatastream.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qcborstreamwriter.o: $(SOURCE_PATH)/src/corelib/serialization/qcborstreamwriter.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qcborvalue.o: $(SOURCE_PATH)/src/corelib/serialization/qcborvalue.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ CFLAGS_BARE = -c -Fo./ -Fdqmake.pdb \
|
|||
-W2 -nologo -O2 \
|
||||
$(CFLAGS_EXTRA) \
|
||||
-I$(QMKSRC) -I$(QMKSRC)\library -I$(QMKSRC)\generators -I$(QMKSRC)\generators\unix -I$(QMKSRC)\generators\win32 -I$(QMKSRC)\generators\mac \
|
||||
-I$(SOURCE_PATH)/src/3rdparty/tinycbor/src \
|
||||
-I$(INC_PATH) -I$(INC_PATH)\QtCore -I$(INC_PATH)\QtCore\$(QT_VERSION) -I$(INC_PATH)\QtCore\$(QT_VERSION)\QtCore \
|
||||
-I$(BUILD_PATH)\src\corelib\global \
|
||||
-I$(SOURCE_PATH)\mkspecs\$(QMAKESPEC) \
|
||||
|
@ -117,6 +118,7 @@ QTOBJS= \
|
|||
qxmlutils.obj \
|
||||
qnumeric.obj \
|
||||
qlogging.obj \
|
||||
qcborstreamwriter.obj \
|
||||
qcborvalue.obj \
|
||||
qjsoncbor.obj \
|
||||
qjsondocument.obj \
|
||||
|
|
|
@ -1329,7 +1329,7 @@
|
|||
\li Value
|
||||
\li Description
|
||||
\row
|
||||
\li no_check_exists
|
||||
\li no_check_exist
|
||||
\li If not set, qmake looks to see if the files to install actually
|
||||
exist. If these files don't exist, qmake doesn’t create the
|
||||
install rule. Use this config value if you need to install
|
||||
|
@ -5407,7 +5407,7 @@
|
|||
\li The exit code of the test will be ignored during \c{make check}.
|
||||
\endtable
|
||||
|
||||
Testcases will often be written with \l{QTest} or \l{TestCase}, but
|
||||
Test cases will often be written with \l{QTest} or \l[QML]{TestCase}, but
|
||||
that is not a requirement to make use of \c{CONFIG+=testcase} and \c{make check}.
|
||||
The only primary requirement is that the test program exit with a zero exit code
|
||||
on success, and a non-zero exit code on failure.
|
||||
|
|
|
@ -1629,17 +1629,24 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
|
|||
}
|
||||
}
|
||||
|
||||
// The symroot is marked by xcodebuild as excluded from Time Machine
|
||||
// backups, as it's a temporary build dir, so we don't want it to be
|
||||
// the same as the possibe in-source dir, as that would leave out
|
||||
// sources from being backed up.
|
||||
t << "\t\t\t\t" << writeSettings("SYMROOT",
|
||||
Option::output_dir + Option::dir_sep + ".xcode") << ";\n";
|
||||
if (Option::output_dir != qmake_getpwd()) {
|
||||
// The SYMROOT is marked by Xcode as excluded from Time Machine
|
||||
// backups, as it's a temporary build dir, but that's fine when
|
||||
// we are shadow building.
|
||||
t << "\t\t\t\t" << writeSettings("SYMROOT", "$(PROJECT_DIR)") << ";\n";
|
||||
} else {
|
||||
// For in-source builds we don't want to exclude the sources
|
||||
// from being backed up, so we point SYMROOT to a temporary
|
||||
// build directory.
|
||||
t << "\t\t\t\t" << writeSettings("SYMROOT", ".xcode") << ";\n";
|
||||
|
||||
// The configuration build dir however is not treated as excluded,
|
||||
// so we can safely point it to the root output dir.
|
||||
t << "\t\t\t\t" << writeSettings("CONFIGURATION_BUILD_DIR",
|
||||
Option::output_dir + Option::dir_sep + "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)") << ";\n";
|
||||
// Then we set the configuration build dir instead, so that the
|
||||
// final build artifacts end up in the place Qt Creator expects.
|
||||
// The disadvantage of using this over SYMROOT is that Xcode will
|
||||
// fail to archive projects that override this variable.
|
||||
t << "\t\t\t\t" << writeSettings("CONFIGURATION_BUILD_DIR",
|
||||
"$(PROJECT_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)") << ";\n";
|
||||
}
|
||||
|
||||
if (!project->isEmpty("DESTDIR")) {
|
||||
ProString dir = project->first("DESTDIR");
|
||||
|
|
|
@ -1247,10 +1247,10 @@ void VcprojGenerator::initDeploymentTool()
|
|||
+ "|" + targetPath
|
||||
+ "|0;";
|
||||
if (!qpaPluginDeployed) {
|
||||
QChar debugInfixChar;
|
||||
QString debugInfix;
|
||||
bool foundGuid = dllName.contains(QLatin1String("Guid"));
|
||||
if (foundGuid)
|
||||
debugInfixChar = QLatin1Char('d');
|
||||
debugInfix = QLatin1Char('d');
|
||||
|
||||
if (foundGuid || dllName.contains(QLatin1String("Gui"))) {
|
||||
QFileInfo info2;
|
||||
|
@ -1258,13 +1258,14 @@ void VcprojGenerator::initDeploymentTool()
|
|||
QString absoluteDllFilePath = dllPath.toQString();
|
||||
if (!absoluteDllFilePath.endsWith(QLatin1Char('/')))
|
||||
absoluteDllFilePath += QLatin1Char('/');
|
||||
absoluteDllFilePath += QLatin1String("../plugins/platforms/qwindows") + debugInfixChar + QLatin1String(".dll");
|
||||
absoluteDllFilePath += QLatin1String("../plugins/platforms/qwindows")
|
||||
+ debugInfix + QLatin1String(".dll");
|
||||
info2 = QFileInfo(absoluteDllFilePath);
|
||||
if (info2.exists())
|
||||
break;
|
||||
}
|
||||
if (info2.exists()) {
|
||||
conf.deployment.AdditionalFiles += QLatin1String("qwindows") + debugInfixChar + QLatin1String(".dll")
|
||||
conf.deployment.AdditionalFiles += QLatin1String("qwindows") + debugInfix + QLatin1String(".dll")
|
||||
+ QLatin1Char('|') + QDir::toNativeSeparators(info2.absolutePath())
|
||||
+ QLatin1Char('|') + targetPath + QLatin1String("\\platforms")
|
||||
+ QLatin1String("|0;");
|
||||
|
|
|
@ -31,7 +31,8 @@ INCLUDEPATH += \
|
|||
generators \
|
||||
generators/unix \
|
||||
generators/win32 \
|
||||
generators/mac
|
||||
generators/mac \
|
||||
../src/3rdparty/tinycbor/src
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
|
@ -116,6 +117,7 @@ SOURCES += \
|
|||
qbytearray.cpp \
|
||||
qbytearraymatcher.cpp \
|
||||
qcalendar.cpp \
|
||||
qcborstreamwriter.cpp \
|
||||
qcborvalue.cpp \
|
||||
qcryptographichash.cpp \
|
||||
qdatetime.cpp \
|
||||
|
@ -175,6 +177,7 @@ HEADERS += \
|
|||
qcalendar.h \
|
||||
qcalendarbackend_p.h \
|
||||
qcalendarmath_p.h \
|
||||
qcborstreamwriter.h \
|
||||
qcborvalue.h \
|
||||
qcborvalue_p.h \
|
||||
qchar.h \
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"Id": "VulkanMemoryAllocator",
|
||||
"Name": "Vulkan Memory Allocator",
|
||||
"QDocModule": "qtrhi",
|
||||
"QDocModule": "qtgui",
|
||||
"Description": "Vulkan Memory Allocator",
|
||||
"QtUsage": "Memory management for the Vulkan backend of QRhi.",
|
||||
|
||||
|
|
|
@ -535,22 +535,10 @@ static double SignedZero(bool sign) {
|
|||
|
||||
|
||||
// Returns true if 'c' is a decimal digit that is valid for the given radix.
|
||||
//
|
||||
// The function is small and could be inlined, but VS2012 emitted a warning
|
||||
// because it constant-propagated the radix and concluded that the last
|
||||
// condition was always true. By moving it into a separate function the
|
||||
// compiler wouldn't warn anymore.
|
||||
#ifdef _MSC_VER
|
||||
#pragma optimize("",off)
|
||||
static bool IsDecimalDigitForRadix(int c, int radix) {
|
||||
return '0' <= c && c <= '9' && (c - '0') < radix;
|
||||
}
|
||||
#pragma optimize("",on)
|
||||
#else
|
||||
static bool inline IsDecimalDigitForRadix(int c, int radix) {
|
||||
return '0' <= c && c <= '9' && (c - '0') < radix;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Returns true if 'c' is a character digit that is valid for the given radix.
|
||||
// The 'a_character' should be 'a' or 'A'.
|
||||
//
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
# define FFD_ATOMIC_ACQUIRE std::memory_order_acquire
|
||||
# define FFD_ATOMIC_RELEASE std::memory_order_release
|
||||
// acq_rel & cst not necessary
|
||||
typedef std::atomic_int ffd_atomic_int;
|
||||
typedef std::atomic<int> ffd_atomic_int;
|
||||
#else
|
||||
# include <stdatomic.h>
|
||||
# define ffd_atomic_pointer(type) _Atomic(type*)
|
||||
|
|
|
@ -103,6 +103,8 @@ FILES="
|
|||
src/pcre2_pattern_info.c
|
||||
src/pcre2_script_run.c
|
||||
src/pcre2_serialize.c
|
||||
src/pcre2_jit_neon_inc.h
|
||||
src/pcre2_jit_simd_inc.h
|
||||
src/pcre2_string_utils.c
|
||||
src/pcre2_study.c
|
||||
src/pcre2_substitute.c
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
"Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.",
|
||||
"Homepage": "http://www.pcre.org/",
|
||||
"Version": "10.33",
|
||||
"DownloadLocation": "https://ftp.pcre.org/pub/pcre/pcre2-10.33.tar.bz2",
|
||||
"Version": "10.34",
|
||||
"DownloadLocation": "https://ftp.pcre.org/pub/pcre/pcre2-10.34.tar.bz2",
|
||||
"License": "BSD 3-clause \"New\" or \"Revised\" License",
|
||||
"LicenseId": "BSD-3-Clause",
|
||||
"LicenseFile": "LICENCE",
|
||||
|
@ -24,8 +24,8 @@ Copyright (c) 2010-2019 Zoltan Herczeg"
|
|||
"Path": "src/sljit",
|
||||
"Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.",
|
||||
"Homepage": "http://www.pcre.org/",
|
||||
"Version": "10.33",
|
||||
"DownloadLocation": "https://ftp.pcre.org/pub/pcre/pcre2-10.33.tar.bz2",
|
||||
"Version": "10.34",
|
||||
"DownloadLocation": "https://ftp.pcre.org/pub/pcre/pcre2-10.34.tar.bz2",
|
||||
"License": "BSD 2-clause \"Simplified\" License",
|
||||
"LicenseId": "BSD-2-Clause",
|
||||
"LicenseFile": "LICENCE",
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
/* This is the public header file for the PCRE library, second API, to be
|
||||
#included by applications that call PCRE2 functions.
|
||||
|
||||
Copyright (c) 2016-2018 University of Cambridge
|
||||
Copyright (c) 2016-2019 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
/* The current PCRE version information. */
|
||||
|
||||
#define PCRE2_MAJOR 10
|
||||
#define PCRE2_MINOR 33
|
||||
#define PCRE2_MINOR 34
|
||||
#define PCRE2_PRERELEASE
|
||||
#define PCRE2_DATE 2019-04-16
|
||||
#define PCRE2_DATE 2019-11-21
|
||||
|
||||
/* 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
|
||||
|
@ -142,6 +142,7 @@ D is inspected during pcre2_dfa_match() execution
|
|||
#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. */
|
||||
|
||||
|
@ -305,6 +306,8 @@ pcre2_pattern_convert(). */
|
|||
#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. */
|
||||
|
@ -390,6 +393,7 @@ released, the numbers must not be changed. */
|
|||
#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() */
|
||||
|
@ -580,7 +584,7 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
|
|||
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 unsigned char *); \
|
||||
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 \
|
||||
|
@ -675,6 +679,8 @@ 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 \
|
||||
|
@ -773,7 +779,8 @@ 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
|
||||
|
@ -838,6 +845,7 @@ pcre2_compile are called by application code. */
|
|||
#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_)
|
||||
|
@ -848,6 +856,7 @@ pcre2_compile are called by application code. */
|
|||
#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_)
|
||||
|
|
|
@ -624,6 +624,13 @@ for(;;)
|
|||
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. */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -323,7 +323,7 @@ data. */
|
|||
|
||||
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
|
||||
pcre2_set_character_tables(pcre2_compile_context *ccontext,
|
||||
const unsigned char *tables)
|
||||
const uint8_t *tables)
|
||||
{
|
||||
ccontext->tables = tables;
|
||||
return 0;
|
||||
|
|
|
@ -173,6 +173,8 @@ static const uint8_t coptable[] = {
|
|||
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 */
|
||||
|
@ -248,6 +250,8 @@ static const uint8_t poptable[] = {
|
|||
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 */
|
||||
|
@ -962,7 +966,7 @@ for (;;)
|
|||
if (ptr >= end_subject)
|
||||
{
|
||||
if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)
|
||||
could_continue = TRUE;
|
||||
return PCRE2_ERROR_PARTIAL;
|
||||
else { ADD_ACTIVE(state_offset + 1, 0); }
|
||||
}
|
||||
break;
|
||||
|
@ -1011,10 +1015,12 @@ for (;;)
|
|||
|
||||
/*-----------------------------------------------------------------*/
|
||||
case OP_EODN:
|
||||
if (clen == 0 && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)
|
||||
could_continue = TRUE;
|
||||
else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - mb->nllen))
|
||||
{ ADD_ACTIVE(state_offset + 1, 0); }
|
||||
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;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
@ -3152,8 +3158,8 @@ for (;;)
|
|||
|
||||
/* 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 we are at the top level and partial
|
||||
matching has been requested, check for appropriate conditions.
|
||||
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
|
||||
|
@ -3165,22 +3171,24 @@ for (;;)
|
|||
|
||||
if (new_count <= 0)
|
||||
{
|
||||
if (rlevel == 1 && /* Top level, and */
|
||||
could_continue && /* Some could go on, and */
|
||||
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 */
|
||||
match_count < 0) /* no matches */
|
||||
) && /* And... */
|
||||
(
|
||||
partial_newline || /* Either partial NL */
|
||||
( /* or ... */
|
||||
ptr >= end_subject && /* End of subject and */
|
||||
ptr > mb->start_used_ptr) /* Inspected non-empty string */
|
||||
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 */
|
||||
}
|
||||
|
@ -3246,6 +3254,11 @@ 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;
|
||||
|
@ -3295,6 +3308,11 @@ 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. */
|
||||
|
||||
|
@ -3404,6 +3422,8 @@ 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;
|
||||
|
@ -3619,7 +3639,10 @@ for (;;)
|
|||
/* 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. */
|
||||
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
|
||||
{
|
||||
|
@ -3633,11 +3656,29 @@ for (;;)
|
|||
(smc = UCHAR21TEST(start_match)) != first_cu &&
|
||||
smc != first_cu2)
|
||||
start_match++;
|
||||
|
||||
#else /* 8-bit code units */
|
||||
PCRE2_SPTR pp1 =
|
||||
memchr(start_match, first_cu, end_subject-start_match);
|
||||
PCRE2_SPTR pp2 =
|
||||
memchr(start_match, first_cu2, end_subject-start_match);
|
||||
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
|
||||
|
@ -3653,7 +3694,7 @@ for (;;)
|
|||
while (start_match < end_subject && UCHAR21TEST(start_match) !=
|
||||
first_cu)
|
||||
start_match++;
|
||||
#else
|
||||
#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
|
||||
|
@ -3740,6 +3781,8 @@ for (;;)
|
|||
|
||||
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
|
||||
|
@ -3753,37 +3796,63 @@ for (;;)
|
|||
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.
|
||||
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. */
|
||||
sufficiently long, but it's worth searching a lot more for unanchored
|
||||
patterns. */
|
||||
|
||||
if (has_req_cu && end_subject - start_match < REQ_CU_MAX)
|
||||
p = start_match + (has_first_cu? 1:0);
|
||||
if (has_req_cu && p > req_cu_ptr)
|
||||
{
|
||||
PCRE2_SPTR p = start_match + (has_first_cu? 1:0);
|
||||
PCRE2_SIZE check_length = end_subject - start_match;
|
||||
|
||||
/* We don't need to repeat the search if we haven't yet reached the
|
||||
place we found it at last time. */
|
||||
|
||||
if (p > req_cu_ptr)
|
||||
if (check_length < REQ_CU_MAX ||
|
||||
(!anchored && check_length < REQ_CU_MAX * 1000))
|
||||
{
|
||||
if (req_cu != req_cu2)
|
||||
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,
|
||||
|
|
|
@ -184,6 +184,8 @@ static const unsigned char compile_error_texts[] =
|
|||
/* 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. */
|
||||
|
@ -268,6 +270,7 @@ static const unsigned char match_error_texts[] =
|
|||
"invalid syntax\0"
|
||||
/* 65 */
|
||||
"internal error - duplicate substitution match\0"
|
||||
"PCRE2_MATCH_INVALID_UTF is not supported for DFA matching\0"
|
||||
;
|
||||
|
||||
|
||||
|
|
|
@ -517,6 +517,7 @@ bytes in a code unit in that mode. */
|
|||
#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)
|
||||
|
||||
|
@ -535,13 +536,14 @@ enum { PCRE2_MATCHEDBY_INTERPRETER, /* pcre2_match() */
|
|||
#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */
|
||||
|
||||
/* The maximum remaining length of subject we are prepared to search for a
|
||||
req_unit match. 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. */
|
||||
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 2000
|
||||
#define REQ_CU_MAX 5000
|
||||
#else
|
||||
#define REQ_CU_MAX 1000
|
||||
#define REQ_CU_MAX 2000
|
||||
#endif
|
||||
|
||||
/* Offsets for the bitmap tables in the cbits set of tables. Each table
|
||||
|
@ -881,12 +883,16 @@ a positive value. */
|
|||
#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"
|
||||
|
@ -1171,12 +1177,16 @@ only. */
|
|||
#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"
|
||||
|
@ -1301,7 +1311,7 @@ enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s,
|
|||
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
|
||||
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
|
||||
|
@ -1499,80 +1509,81 @@ enum {
|
|||
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, and the four
|
||||
asserts must remain in order. */
|
||||
/* 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, /* 130 Atomic group, contains captures */
|
||||
OP_SCRIPT_RUN, /* 131 Non-capture, but check characters' scripts */
|
||||
OP_BRA, /* 132 Start of non-capturing bracket */
|
||||
OP_BRAPOS, /* 133 Ditto, with unlimited, possessive repeat */
|
||||
OP_CBRA, /* 134 Start of capturing bracket */
|
||||
OP_CBRAPOS, /* 135 Ditto, with unlimited, possessive repeat */
|
||||
OP_COND, /* 136 Conditional group */
|
||||
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, /* 137 Start of non-capturing bracket, check empty */
|
||||
OP_SBRAPOS, /* 138 Ditto, with unlimited, possessive repeat */
|
||||
OP_SCBRA, /* 139 Start of capturing bracket, check empty */
|
||||
OP_SCBRAPOS, /* 140 Ditto, with unlimited, possessive repeat */
|
||||
OP_SCOND, /* 141 Conditional group, check empty */
|
||||
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, /* 142 Used to hold a capture number as condition */
|
||||
OP_DNCREF, /* 143 Used to point to duplicate names as a condition */
|
||||
OP_RREF, /* 144 Used to hold a recursion number as condition */
|
||||
OP_DNRREF, /* 145 Used to point to duplicate names as a condition */
|
||||
OP_FALSE, /* 146 Always false (used by DEFINE and VERSION) */
|
||||
OP_TRUE, /* 147 Always true (used by VERSION) */
|
||||
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, /* 148 These two must remain together and in this */
|
||||
OP_BRAMINZERO, /* 149 order. */
|
||||
OP_BRAPOSZERO, /* 150 */
|
||||
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, /* 151 always has an argument */
|
||||
OP_PRUNE, /* 152 */
|
||||
OP_PRUNE_ARG, /* 153 same, but with argument */
|
||||
OP_SKIP, /* 154 */
|
||||
OP_SKIP_ARG, /* 155 same, but with argument */
|
||||
OP_THEN, /* 156 */
|
||||
OP_THEN_ARG, /* 157 same, but with argument */
|
||||
OP_COMMIT, /* 158 */
|
||||
OP_COMMIT_ARG, /* 159 same, but with argument */
|
||||
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, /* 160 */
|
||||
OP_ACCEPT, /* 161 */
|
||||
OP_ASSERT_ACCEPT, /* 162 Used inside assertions */
|
||||
OP_CLOSE, /* 163 Used before OP_ACCEPT to close open captures */
|
||||
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, /* 164 */
|
||||
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, /* 165 */
|
||||
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
|
||||
|
@ -1585,7 +1596,7 @@ enum {
|
|||
/* *** 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_exec.c that must be updated. */
|
||||
pcre2_dfa_match.c that must be updated. */
|
||||
|
||||
|
||||
/* This macro defines textual names for all the opcodes. These are used only
|
||||
|
@ -1618,7 +1629,9 @@ some cases doesn't actually use these names at all). */
|
|||
"class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \
|
||||
"Recurse", "Callout", "CalloutStr", \
|
||||
"Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \
|
||||
"Reverse", "Assert", "Assert not", "AssertB", "AssertB not", \
|
||||
"Reverse", "Assert", "Assert not", \
|
||||
"Assert back", "Assert back not", \
|
||||
"Non-atomic assert", "Non-atomic assert back", \
|
||||
"Once", \
|
||||
"Script run", \
|
||||
"Bra", "BraPos", "CBra", "CBraPos", \
|
||||
|
@ -1703,6 +1716,8 @@ in UTF-8 mode. The code that uses this table must know about such things. */
|
|||
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 */ \
|
||||
|
|
|
@ -205,19 +205,19 @@ 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. When code points can be greater than 255, a check is needed before
|
||||
accessing these tables. */
|
||||
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 */
|
||||
#define TABLE_GET(c, table, default) ((table)[c])
|
||||
|
||||
#else /* Code units are 16 or 32 bits */
|
||||
#define CHMAX_255(c) ((c) <= 255u)
|
||||
|
@ -228,7 +228,6 @@ accessing these tables. */
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
/* ----------------- Character-handling macros ----------------- */
|
||||
|
||||
/* There is a proposed future special "UTF-21" mode, in which only the lowest
|
||||
|
@ -854,6 +853,7 @@ typedef struct match_block {
|
|||
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 */
|
||||
|
@ -866,6 +866,7 @@ typedef struct match_block {
|
|||
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 */
|
||||
|
@ -908,6 +909,7 @@ typedef struct dfa_match_block {
|
|||
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 */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -74,7 +74,6 @@ Arguments:
|
|||
options option bits
|
||||
match_data points to a match_data block
|
||||
mcontext points to a match context
|
||||
jit_stack points to a JIT stack
|
||||
|
||||
Returns: > 0 => success; value is the number of ovector pairs filled
|
||||
= 0 => success, but ovector is not big enough
|
||||
|
|
|
@ -0,0 +1,321 @@
|
|||
/*************************************************
|
||||
* 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);
|
||||
# else
|
||||
PCRE2_UCHAR char1b = ic.c.c2;
|
||||
PCRE2_UCHAR char2b = ic.c.c4;
|
||||
if (char1a == char1b)
|
||||
cmp1a = VDUPQ(char1a);
|
||||
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);
|
||||
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);
|
||||
|
||||
data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
|
||||
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
|
||||
data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,993 @@
|
|||
/*************************************************
|
||||
* 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
|
||||
}
|
||||
|
||||
#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 */
|
|
@ -147,4 +147,15 @@ for (i = 0; i < 256; i++)
|
|||
return yield;
|
||||
}
|
||||
|
||||
#ifndef DFTABLES
|
||||
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 */
|
||||
|
|
|
@ -415,8 +415,7 @@ if (caseless)
|
|||
else
|
||||
#endif
|
||||
|
||||
/* Not in UTF mode */
|
||||
|
||||
/* Not in UTF mode */
|
||||
{
|
||||
for (; length > 0; length--)
|
||||
{
|
||||
|
@ -491,27 +490,32 @@ heap is used for a larger vector.
|
|||
*************************************************/
|
||||
|
||||
/* These macros pack up tests that are used for partial matching several times
|
||||
in the code. We set the "hit end" flag if the pointer is at the end of the
|
||||
subject and also past the earliest inspected character (i.e. something has been
|
||||
matched, even if not part of the actual matched string). For hard partial
|
||||
matching, we then return immediately. The second one is used when we already
|
||||
know we are past the end of the subject. */
|
||||
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 (mb->partial != 0 && Feptr >= mb->end_subject && \
|
||||
Feptr > mb->start_used_ptr) \
|
||||
if (Feptr >= mb->end_subject) \
|
||||
{ \
|
||||
mb->hitend = TRUE; \
|
||||
if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \
|
||||
SCHECK_PARTIAL(); \
|
||||
}
|
||||
|
||||
#define SCHECK_PARTIAL()\
|
||||
if (mb->partial != 0 && Feptr > mb->start_used_ptr) \
|
||||
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. */
|
||||
|
@ -5127,6 +5131,8 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
|||
|
||||
case OP_ASSERT:
|
||||
case OP_ASSERTBACK:
|
||||
case OP_ASSERT_NA:
|
||||
case OP_ASSERTBACK_NA:
|
||||
Lframe_type = GF_NOCAPTURE | Fop;
|
||||
for (;;)
|
||||
{
|
||||
|
@ -5412,7 +5418,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
|||
{
|
||||
while (number-- > 0)
|
||||
{
|
||||
if (Feptr <= mb->start_subject) RRETURN(MATCH_NOMATCH);
|
||||
if (Feptr <= mb->check_subject) RRETURN(MATCH_NOMATCH);
|
||||
Feptr--;
|
||||
BACKCHAR(Feptr);
|
||||
}
|
||||
|
@ -5420,7 +5426,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
|||
else
|
||||
#endif
|
||||
|
||||
/* No UTF-8 support, or not in UTF-8 mode: count is byte count */
|
||||
/* 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);
|
||||
|
@ -5472,15 +5478,16 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
|||
|
||||
/* If we are at the end of an assertion that is a condition, return a
|
||||
match, discarding any intermediate backtracking points. Copy back 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. */
|
||||
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);
|
||||
}
|
||||
|
@ -5496,10 +5503,20 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
|||
case OP_SCOND:
|
||||
break;
|
||||
|
||||
/* Positive assertions are like OP_ONCE, except that in addition the
|
||||
/* 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;
|
||||
|
@ -5640,7 +5657,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
|||
|
||||
case OP_EOD:
|
||||
if (Feptr < mb->end_subject) RRETURN(MATCH_NOMATCH);
|
||||
SCHECK_PARTIAL();
|
||||
if (mb->partial != 0)
|
||||
{
|
||||
mb->hitend = TRUE;
|
||||
if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
|
||||
}
|
||||
Fecode++;
|
||||
break;
|
||||
|
||||
|
@ -5665,7 +5686,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
|||
|
||||
/* Either at end of string or \n before end. */
|
||||
|
||||
SCHECK_PARTIAL();
|
||||
if (mb->partial != 0)
|
||||
{
|
||||
mb->hitend = TRUE;
|
||||
if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
|
||||
}
|
||||
Fecode++;
|
||||
break;
|
||||
|
||||
|
@ -5743,7 +5768,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
|||
|
||||
case OP_NOT_WORD_BOUNDARY:
|
||||
case OP_WORD_BOUNDARY:
|
||||
if (Feptr == mb->start_subject) prev_is_word = FALSE; else
|
||||
if (Feptr == mb->check_subject) prev_is_word = FALSE; else
|
||||
{
|
||||
PCRE2_SPTR lastptr = Feptr - 1;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
|
@ -5946,6 +5971,7 @@ 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 */
|
||||
|
@ -5999,9 +6025,9 @@ Arguments:
|
|||
|
||||
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
|
||||
= -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
|
||||
|
@ -6014,7 +6040,6 @@ 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;
|
||||
|
@ -6022,6 +6047,11 @@ BOOL has_req_cu = FALSE;
|
|||
BOOL startline;
|
||||
BOOL utf;
|
||||
|
||||
#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;
|
||||
|
@ -6029,10 +6059,23 @@ 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 = NULL;
|
||||
PCRE2_SPTR match_partial = NULL;
|
||||
PCRE2_SPTR start_partial;
|
||||
PCRE2_SPTR match_partial;
|
||||
|
||||
#ifdef SUPPORT_JIT
|
||||
BOOL use_jit;
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_UNICODE
|
||||
BOOL allow_invalid;
|
||||
uint32_t fragment_options = 0;
|
||||
#ifdef SUPPORT_JIT
|
||||
BOOL jit_checked_utf = FALSE;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
PCRE2_SIZE frame_size;
|
||||
|
||||
|
@ -6059,7 +6102,7 @@ if (length == PCRE2_ZERO_TERMINATED)
|
|||
length = PRIV(strlen)(subject);
|
||||
was_zero_terminated = 1;
|
||||
}
|
||||
end_subject = subject + length;
|
||||
true_end_subject = end_subject = subject + length;
|
||||
|
||||
/* Plausibility checks */
|
||||
|
||||
|
@ -6095,12 +6138,24 @@ options |= (re->flags & FF) / ((FF & (~FF+1)) / (OO & (~OO+1)));
|
|||
#undef FF
|
||||
#undef OO
|
||||
|
||||
/* These two settings are used in the code for checking a UTF string that
|
||||
follows immediately afterwards. Other values in the mb block are used only
|
||||
during interpretive processing, not when the JIT support is in use, so they are
|
||||
set up later. */
|
||||
/* 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 parameters. */
|
||||
|
||||
utf = (re->overall_options & PCRE2_UTF) != 0;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
allow_invalid = (re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0;
|
||||
#endif
|
||||
|
||||
/* Convert the partial matching flags into an integer. */
|
||||
|
||||
mb->partial = ((options & PCRE2_PARTIAL_HARD) != 0)? 2 :
|
||||
((options & PCRE2_PARTIAL_SOFT) != 0)? 1 : 0;
|
||||
|
||||
|
@ -6111,61 +6166,6 @@ if (mb->partial != 0 &&
|
|||
((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)
|
||||
return PCRE2_ERROR_BADOPTION;
|
||||
|
||||
/* 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. 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)
|
||||
check_subject -= re->max_lookbehind;
|
||||
else
|
||||
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 - (check_subject - subject), &(match_data->startchar));
|
||||
if (match_data->rc != 0)
|
||||
{
|
||||
match_data->startchar += check_subject - subject;
|
||||
return match_data->rc;
|
||||
}
|
||||
}
|
||||
#endif /* SUPPORT_UNICODE */
|
||||
|
||||
/* It is an error to set an offset limit without setting the flag at compile
|
||||
time. */
|
||||
|
||||
|
@ -6184,15 +6184,89 @@ if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)
|
|||
}
|
||||
match_data->subject = NULL;
|
||||
|
||||
/* If the pattern was successfully studied with JIT support, 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. Fallback to the normal code path if
|
||||
an unsupported option is set or if JIT returns BADOPTION (which means that the
|
||||
selected normal or partial matching mode was not compiled). */
|
||||
/* 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 (re->executable_jit != NULL && (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0)
|
||||
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)
|
||||
|
@ -6209,10 +6283,152 @@ if (re->executable_jit != NULL && (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0)
|
|||
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
|
||||
|
||||
/* Carry on with non-JIT matching. A NULL match context means "use a default
|
||||
context", but we take the memory control functions from the pattern. */
|
||||
/* 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)
|
||||
{
|
||||
|
@ -6224,8 +6440,8 @@ 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)?
|
||||
end_subject : subject + mcontext->offset_limit;
|
||||
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. */
|
||||
|
@ -6236,7 +6452,8 @@ cb.subject = subject;
|
|||
cb.subject_length = (PCRE2_SIZE)(end_subject - subject);
|
||||
cb.callout_flags = 0;
|
||||
|
||||
/* Fill in the remaining fields in the match block. */
|
||||
/* 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;
|
||||
|
@ -6245,13 +6462,11 @@ mb->start_subject = subject;
|
|||
mb->start_offset = start_offset;
|
||||
mb->end_subject = end_subject;
|
||||
mb->hasthen = (re->flags & PCRE2_HASTHEN) != 0;
|
||||
|
||||
mb->moptions = options; /* Match options */
|
||||
mb->poptions = re->overall_options; /* Pattern options */
|
||||
|
||||
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 */
|
||||
mb->hitend = FALSE;
|
||||
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. */
|
||||
|
@ -6404,6 +6619,13 @@ if ((re->flags & PCRE2_LASTSET) != 0)
|
|||
/* 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;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
PCRE2_SPTR new_start_match;
|
||||
|
@ -6473,7 +6695,10 @@ for(;;)
|
|||
/* 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. */
|
||||
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
|
||||
{
|
||||
|
@ -6487,11 +6712,29 @@ for(;;)
|
|||
(smc = UCHAR21TEST(start_match)) != first_cu &&
|
||||
smc != first_cu2)
|
||||
start_match++;
|
||||
|
||||
#else /* 8-bit code units */
|
||||
PCRE2_SPTR pp1 =
|
||||
memchr(start_match, first_cu, end_subject-start_match);
|
||||
PCRE2_SPTR pp2 =
|
||||
memchr(start_match, first_cu2, end_subject-start_match);
|
||||
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
|
||||
|
@ -6523,7 +6766,7 @@ for(;;)
|
|||
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 && start_match >= mb->end_subject)
|
||||
if (mb->partial == 0 && start_match >= mb->end_subject)
|
||||
{
|
||||
rc = MATCH_NOMATCH;
|
||||
break;
|
||||
|
@ -6582,7 +6825,7 @@ for(;;)
|
|||
|
||||
/* See comment above in first_cu checking about the next few lines. */
|
||||
|
||||
if (!mb->partial && start_match >= mb->end_subject)
|
||||
if (mb->partial == 0 && start_match >= mb->end_subject)
|
||||
{
|
||||
rc = MATCH_NOMATCH;
|
||||
break;
|
||||
|
@ -6596,8 +6839,10 @@ for(;;)
|
|||
|
||||
/* The following two optimizations must be disabled for partial matching. */
|
||||
|
||||
if (!mb->partial)
|
||||
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
|
||||
|
@ -6621,60 +6866,57 @@ for(;;)
|
|||
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. */
|
||||
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. */
|
||||
|
||||
if (has_req_cu && end_subject - start_match < REQ_CU_MAX)
|
||||
p = start_match + (has_first_cu? 1:0);
|
||||
if (has_req_cu && p > req_cu_ptr)
|
||||
{
|
||||
PCRE2_SPTR p = start_match + (has_first_cu? 1:0);
|
||||
PCRE2_SIZE check_length = end_subject - start_match;
|
||||
|
||||
/* We don't need to repeat the search if we haven't yet reached the
|
||||
place we found it last time round the bumpalong loop. */
|
||||
|
||||
if (p > req_cu_ptr)
|
||||
if (check_length < REQ_CU_MAX ||
|
||||
(!anchored && check_length < REQ_CU_MAX * 1000))
|
||||
{
|
||||
if (p < end_subject)
|
||||
if (req_cu != req_cu2) /* Caseless */
|
||||
{
|
||||
if (req_cu != req_cu2) /* Caseless */
|
||||
{
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 8
|
||||
do
|
||||
{
|
||||
uint32_t pp = UCHAR21INCTEST(p);
|
||||
if (pp == req_cu || pp == req_cu2) { p--; break; }
|
||||
}
|
||||
while (p < end_subject);
|
||||
|
||||
#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 */
|
||||
while (p < end_subject)
|
||||
{
|
||||
uint32_t pp = UCHAR21INCTEST(p);
|
||||
if (pp == req_cu || pp == req_cu2) { p--; break; }
|
||||
}
|
||||
|
||||
/* The caseful case */
|
||||
|
||||
else
|
||||
{
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 8
|
||||
do
|
||||
{
|
||||
if (UCHAR21INCTEST(p) == req_cu) { p--; break; }
|
||||
}
|
||||
while (p < end_subject);
|
||||
|
||||
#else /* 8-bit code units */
|
||||
p = memchr(p, req_cu, end_subject - p);
|
||||
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
|
||||
}
|
||||
#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,
|
||||
|
@ -6714,6 +6956,11 @@ for(;;)
|
|||
|
||||
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;
|
||||
|
@ -6839,6 +7086,68 @@ for(;;)
|
|||
|
||||
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)
|
||||
|
|
|
@ -7,7 +7,7 @@ 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
|
||||
New API code Copyright (c) 2016-2019 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -150,4 +150,17 @@ 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 */
|
||||
|
|
|
@ -88,11 +88,13 @@ Arguments:
|
|||
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
|
||||
or back reference to duplicate name/number
|
||||
-2 internal error (missing capturing bracket)
|
||||
-3 internal error (opcode not listed)
|
||||
*/
|
||||
|
@ -103,6 +105,7 @@ find_minlength(const pcre2_real_code *re, PCRE2_SPTR code,
|
|||
int *backref_cache)
|
||||
{
|
||||
int length = -1;
|
||||
int branchlength = 0;
|
||||
int prev_cap_recno = -1;
|
||||
int prev_cap_d = 0;
|
||||
int prev_recurse_recno = -1;
|
||||
|
@ -110,9 +113,9 @@ int prev_recurse_d = 0;
|
|||
uint32_t once_fudge = 0;
|
||||
BOOL had_recurse = FALSE;
|
||||
BOOL dupcapused = (re->flags & PCRE2_DUPCAPUSED) != 0;
|
||||
recurse_check this_recurse;
|
||||
int branchlength = 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. */
|
||||
|
||||
|
@ -128,16 +131,20 @@ 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, stop. */
|
||||
passes 16-bits, reset to that value and skip the rest of the branch. */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int d, min, recno;
|
||||
PCRE2_UCHAR *cs, *ce;
|
||||
PCRE2_UCHAR op = *cc;
|
||||
PCRE2_UCHAR op, *cs, *ce;
|
||||
|
||||
if (branchlength >= UINT16_MAX) return UINT16_MAX;
|
||||
if (branchlength >= UINT16_MAX)
|
||||
{
|
||||
branchlength = UINT16_MAX;
|
||||
cc = (PCRE2_UCHAR *)nextbranch;
|
||||
}
|
||||
|
||||
op = *cc;
|
||||
switch (op)
|
||||
{
|
||||
case OP_COND:
|
||||
|
@ -206,7 +213,9 @@ for (;;)
|
|||
cc += 1 + LINK_SIZE;
|
||||
break;
|
||||
|
||||
/* ACCEPT makes things far too complicated; we have to give up. */
|
||||
/* 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:
|
||||
|
@ -214,9 +223,9 @@ for (;;)
|
|||
|
||||
/* 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 an
|
||||
ACCEPT was previously encountered, use the length that was in force at that
|
||||
time, and pass back the shortest ACCEPT length. */
|
||||
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:
|
||||
|
@ -226,7 +235,8 @@ for (;;)
|
|||
case OP_END:
|
||||
if (length < 0 || (!had_recurse && branchlength < length))
|
||||
length = branchlength;
|
||||
if (op != OP_ALT) return length;
|
||||
if (op != OP_ALT || length == 0) return length;
|
||||
nextbranch = cc + GET(cc, 1);
|
||||
cc += 1 + LINK_SIZE;
|
||||
branchlength = 0;
|
||||
had_recurse = FALSE;
|
||||
|
@ -238,6 +248,8 @@ for (;;)
|
|||
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 */
|
||||
|
||||
|
@ -451,15 +463,17 @@ for (;;)
|
|||
|
||||
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. */
|
||||
that case we must set the minimum length to zero.
|
||||
|
||||
/* Duplicate named pattern back reference. We cannot reliably find a length
|
||||
for this if duplicate numbers are present in the pattern. */
|
||||
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) return -1;
|
||||
if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
|
||||
if (!dupcapused && (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
|
||||
{
|
||||
int count = GET2(cc, 1+IMM2_SIZE);
|
||||
PCRE2_UCHAR *slot =
|
||||
|
@ -482,28 +496,32 @@ for (;;)
|
|||
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 (cc > cs && cc < ce) /* Simple recursion */
|
||||
|
||||
dd = 0;
|
||||
if (!dupcapused ||
|
||||
(PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)
|
||||
{
|
||||
dd = 0;
|
||||
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 */
|
||||
if (cc > cs && cc < ce) /* Simple recursion */
|
||||
{
|
||||
dd = 0;
|
||||
had_recurse = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_recurse.prev = recurses;
|
||||
this_recurse.group = cs;
|
||||
dd = find_minlength(re, cs, startcode, utf, &this_recurse,
|
||||
countptr, backref_cache);
|
||||
if (dd < 0) return dd;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,48 +539,51 @@ for (;;)
|
|||
cc += 1 + 2*IMM2_SIZE;
|
||||
goto REPEAT_BACK_REFERENCE;
|
||||
|
||||
/* Single back reference. We cannot find a length for this if duplicate
|
||||
numbers are present in the pattern. */
|
||||
/* Single back reference by number. References by name are converted to by
|
||||
number when there is no duplication. */
|
||||
|
||||
case OP_REF:
|
||||
case OP_REFI:
|
||||
if (dupcapused) return -1;
|
||||
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 (cc > cs && cc < ce) /* Simple recursion */
|
||||
|
||||
if (!dupcapused ||
|
||||
(PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)
|
||||
{
|
||||
d = 0;
|
||||
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 */
|
||||
if (cc > cs && cc < ce) /* Simple recursion */
|
||||
{
|
||||
d = 0;
|
||||
had_recurse = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else d = 0;
|
||||
|
||||
backref_cache[recno] = d;
|
||||
for (i = backref_cache[0] + 1; i < recno; i++) backref_cache[i] = -1;
|
||||
|
@ -888,7 +909,7 @@ if (table_limit != 32) for (c = 24; c < 32; c++) re->start_bitmap[c] = 0xff;
|
|||
|
||||
|
||||
/*************************************************
|
||||
* Create bitmap of starting bytes *
|
||||
* Create bitmap of starting code units *
|
||||
*************************************************/
|
||||
|
||||
/* This function scans a compiled unanchored expression recursively and
|
||||
|
@ -938,6 +959,9 @@ do
|
|||
{
|
||||
int rc;
|
||||
uint8_t *classmap = NULL;
|
||||
#ifdef SUPPORT_WIDE_CHARS
|
||||
PCRE2_UCHAR xclassflags;
|
||||
#endif
|
||||
|
||||
switch(*tcode)
|
||||
{
|
||||
|
@ -1078,6 +1102,7 @@ do
|
|||
case OP_ONCE:
|
||||
case OP_SCRIPT_RUN:
|
||||
case OP_ASSERT:
|
||||
case OP_ASSERT_NA:
|
||||
rc = set_start_bits(re, tcode, utf);
|
||||
if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
|
||||
if (rc == SSB_DONE) try_next = FALSE; else
|
||||
|
@ -1120,6 +1145,7 @@ do
|
|||
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;
|
||||
|
@ -1444,20 +1470,59 @@ do
|
|||
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 always potential starters. */
|
||||
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:
|
||||
if ((tcode[1 + LINK_SIZE] & XCL_HASPROP) != 0 ||
|
||||
(tcode[1 + LINK_SIZE] & (XCL_MAP|XCL_NOT)) == XCL_NOT)
|
||||
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 = ((tcode[1 + LINK_SIZE] & XCL_MAP) == 0)? NULL :
|
||||
classmap = ((xclassflags & XCL_MAP) == 0)? NULL :
|
||||
(uint8_t *)(tcode + 1 + LINK_SIZE + 1);
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
|
||||
|
@ -1499,6 +1564,9 @@ do
|
|||
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
|
||||
|
@ -1569,7 +1637,9 @@ return yield;
|
|||
/* This function is handed a compiled expression that it must study to produce
|
||||
information that will speed up the matching.
|
||||
|
||||
Argument: points to the compiled expression
|
||||
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
|
||||
|
@ -1579,7 +1649,6 @@ Returns: 0 normally; non-zero should never normally occur
|
|||
int
|
||||
PRIV(study)(pcre2_real_code *re)
|
||||
{
|
||||
int min;
|
||||
int count = 0;
|
||||
PCRE2_UCHAR *code;
|
||||
BOOL utf = (re->overall_options & PCRE2_UTF) != 0;
|
||||
|
@ -1597,25 +1666,121 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)
|
|||
{
|
||||
int rc = set_start_bits(re, code, utf);
|
||||
if (rc == SSB_UNKNOWN) return 1;
|
||||
if (rc == SSB_DONE) re->flags |= PCRE2_FIRSTMAPSET;
|
||||
|
||||
/* 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. */
|
||||
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 8
|
||||
if (c > 127) goto DONE;
|
||||
#endif
|
||||
if (a < 0) a = c; /* First one found */
|
||||
else if (b < 0) /* Second one found */
|
||||
{
|
||||
int d = TABLE_GET((unsigned int)c, re->tables + fcc_offset, c);
|
||||
|
||||
#ifdef SUPPORT_UNICODE
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 8
|
||||
if (utf && UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */
|
||||
#else /* 16-bit or 32-bit */
|
||||
if (UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */
|
||||
if (utf && c > 127) d = UCD_OTHERCASE(c);
|
||||
#endif /* Code width */
|
||||
#endif /* SUPPORT_UNICODE */
|
||||
|
||||
if (d != a) goto DONE; /* Not other case of a */
|
||||
b = c;
|
||||
}
|
||||
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 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. */
|
||||
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) == 0 &&
|
||||
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 (*ACCEPT) or over-complex regex */
|
||||
case -1: /* \C in UTF mode or over-complex regex */
|
||||
break; /* Leave minlength unchanged (will be zero) */
|
||||
|
||||
case -2:
|
||||
|
@ -1625,8 +1790,7 @@ if ((re->flags & PCRE2_MATCH_EMPTY) == 0 &&
|
|||
return 3; /* unrecognized opcode */
|
||||
|
||||
default:
|
||||
if (min > UINT16_MAX) min = UINT16_MAX;
|
||||
re->minlength = min;
|
||||
re->minlength = (min > UINT16_MAX)? UINT16_MAX : min;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -279,6 +279,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
|||
#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"
|
||||
|
@ -348,6 +349,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
|||
#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"
|
||||
|
@ -355,6 +357,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
|||
#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"
|
||||
|
@ -419,6 +422,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
|
|||
#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"
|
||||
|
@ -474,6 +478,7 @@ const char PRIV(utt_names)[] =
|
|||
STRING_Duployan0
|
||||
STRING_Egyptian_Hieroglyphs0
|
||||
STRING_Elbasan0
|
||||
STRING_Elymaic0
|
||||
STRING_Ethiopic0
|
||||
STRING_Georgian0
|
||||
STRING_Glagolitic0
|
||||
|
@ -543,6 +548,7 @@ const char PRIV(utt_names)[] =
|
|||
STRING_Myanmar0
|
||||
STRING_N0
|
||||
STRING_Nabataean0
|
||||
STRING_Nandinagari0
|
||||
STRING_Nd0
|
||||
STRING_New_Tai_Lue0
|
||||
STRING_Newa0
|
||||
|
@ -550,6 +556,7 @@ const char PRIV(utt_names)[] =
|
|||
STRING_Nl0
|
||||
STRING_No0
|
||||
STRING_Nushu0
|
||||
STRING_Nyiakeng_Puachue_Hmong0
|
||||
STRING_Ogham0
|
||||
STRING_Ol_Chiki0
|
||||
STRING_Old_Hungarian0
|
||||
|
@ -614,6 +621,7 @@ const char PRIV(utt_names)[] =
|
|||
STRING_Ugaritic0
|
||||
STRING_Unknown0
|
||||
STRING_Vai0
|
||||
STRING_Wancho0
|
||||
STRING_Warang_Citi0
|
||||
STRING_Xan0
|
||||
STRING_Xps0
|
||||
|
@ -669,158 +677,162 @@ const ucp_type_table PRIV(utt)[] = {
|
|||
{ 299, PT_SC, ucp_Duployan },
|
||||
{ 308, PT_SC, ucp_Egyptian_Hieroglyphs },
|
||||
{ 329, PT_SC, ucp_Elbasan },
|
||||
{ 337, PT_SC, ucp_Ethiopic },
|
||||
{ 346, PT_SC, ucp_Georgian },
|
||||
{ 355, PT_SC, ucp_Glagolitic },
|
||||
{ 366, PT_SC, ucp_Gothic },
|
||||
{ 373, PT_SC, ucp_Grantha },
|
||||
{ 381, PT_SC, ucp_Greek },
|
||||
{ 387, PT_SC, ucp_Gujarati },
|
||||
{ 396, PT_SC, ucp_Gunjala_Gondi },
|
||||
{ 410, PT_SC, ucp_Gurmukhi },
|
||||
{ 419, PT_SC, ucp_Han },
|
||||
{ 423, PT_SC, ucp_Hangul },
|
||||
{ 430, PT_SC, ucp_Hanifi_Rohingya },
|
||||
{ 446, PT_SC, ucp_Hanunoo },
|
||||
{ 454, PT_SC, ucp_Hatran },
|
||||
{ 461, PT_SC, ucp_Hebrew },
|
||||
{ 468, PT_SC, ucp_Hiragana },
|
||||
{ 477, PT_SC, ucp_Imperial_Aramaic },
|
||||
{ 494, PT_SC, ucp_Inherited },
|
||||
{ 504, PT_SC, ucp_Inscriptional_Pahlavi },
|
||||
{ 526, PT_SC, ucp_Inscriptional_Parthian },
|
||||
{ 549, PT_SC, ucp_Javanese },
|
||||
{ 558, PT_SC, ucp_Kaithi },
|
||||
{ 565, PT_SC, ucp_Kannada },
|
||||
{ 573, PT_SC, ucp_Katakana },
|
||||
{ 582, PT_SC, ucp_Kayah_Li },
|
||||
{ 591, PT_SC, ucp_Kharoshthi },
|
||||
{ 602, PT_SC, ucp_Khmer },
|
||||
{ 608, PT_SC, ucp_Khojki },
|
||||
{ 615, PT_SC, ucp_Khudawadi },
|
||||
{ 625, PT_GC, ucp_L },
|
||||
{ 627, PT_LAMP, 0 },
|
||||
{ 630, PT_SC, ucp_Lao },
|
||||
{ 634, PT_SC, ucp_Latin },
|
||||
{ 640, PT_SC, ucp_Lepcha },
|
||||
{ 647, PT_SC, ucp_Limbu },
|
||||
{ 653, PT_SC, ucp_Linear_A },
|
||||
{ 662, PT_SC, ucp_Linear_B },
|
||||
{ 671, PT_SC, ucp_Lisu },
|
||||
{ 676, PT_PC, ucp_Ll },
|
||||
{ 679, PT_PC, ucp_Lm },
|
||||
{ 682, PT_PC, ucp_Lo },
|
||||
{ 685, PT_PC, ucp_Lt },
|
||||
{ 688, PT_PC, ucp_Lu },
|
||||
{ 691, PT_SC, ucp_Lycian },
|
||||
{ 698, PT_SC, ucp_Lydian },
|
||||
{ 705, PT_GC, ucp_M },
|
||||
{ 707, PT_SC, ucp_Mahajani },
|
||||
{ 716, PT_SC, ucp_Makasar },
|
||||
{ 724, PT_SC, ucp_Malayalam },
|
||||
{ 734, PT_SC, ucp_Mandaic },
|
||||
{ 742, PT_SC, ucp_Manichaean },
|
||||
{ 753, PT_SC, ucp_Marchen },
|
||||
{ 761, PT_SC, ucp_Masaram_Gondi },
|
||||
{ 775, PT_PC, ucp_Mc },
|
||||
{ 778, PT_PC, ucp_Me },
|
||||
{ 781, PT_SC, ucp_Medefaidrin },
|
||||
{ 793, PT_SC, ucp_Meetei_Mayek },
|
||||
{ 806, PT_SC, ucp_Mende_Kikakui },
|
||||
{ 820, PT_SC, ucp_Meroitic_Cursive },
|
||||
{ 837, PT_SC, ucp_Meroitic_Hieroglyphs },
|
||||
{ 858, PT_SC, ucp_Miao },
|
||||
{ 863, PT_PC, ucp_Mn },
|
||||
{ 866, PT_SC, ucp_Modi },
|
||||
{ 871, PT_SC, ucp_Mongolian },
|
||||
{ 881, PT_SC, ucp_Mro },
|
||||
{ 885, PT_SC, ucp_Multani },
|
||||
{ 893, PT_SC, ucp_Myanmar },
|
||||
{ 901, PT_GC, ucp_N },
|
||||
{ 903, PT_SC, ucp_Nabataean },
|
||||
{ 913, PT_PC, ucp_Nd },
|
||||
{ 916, PT_SC, ucp_New_Tai_Lue },
|
||||
{ 928, PT_SC, ucp_Newa },
|
||||
{ 933, PT_SC, ucp_Nko },
|
||||
{ 937, PT_PC, ucp_Nl },
|
||||
{ 940, PT_PC, ucp_No },
|
||||
{ 943, PT_SC, ucp_Nushu },
|
||||
{ 949, PT_SC, ucp_Ogham },
|
||||
{ 955, PT_SC, ucp_Ol_Chiki },
|
||||
{ 964, PT_SC, ucp_Old_Hungarian },
|
||||
{ 978, PT_SC, ucp_Old_Italic },
|
||||
{ 989, PT_SC, ucp_Old_North_Arabian },
|
||||
{ 1007, PT_SC, ucp_Old_Permic },
|
||||
{ 1018, PT_SC, ucp_Old_Persian },
|
||||
{ 1030, PT_SC, ucp_Old_Sogdian },
|
||||
{ 1042, PT_SC, ucp_Old_South_Arabian },
|
||||
{ 1060, PT_SC, ucp_Old_Turkic },
|
||||
{ 1071, PT_SC, ucp_Oriya },
|
||||
{ 1077, PT_SC, ucp_Osage },
|
||||
{ 1083, PT_SC, ucp_Osmanya },
|
||||
{ 1091, PT_GC, ucp_P },
|
||||
{ 1093, PT_SC, ucp_Pahawh_Hmong },
|
||||
{ 1106, PT_SC, ucp_Palmyrene },
|
||||
{ 1116, PT_SC, ucp_Pau_Cin_Hau },
|
||||
{ 1128, PT_PC, ucp_Pc },
|
||||
{ 1131, PT_PC, ucp_Pd },
|
||||
{ 1134, PT_PC, ucp_Pe },
|
||||
{ 1137, PT_PC, ucp_Pf },
|
||||
{ 1140, PT_SC, ucp_Phags_Pa },
|
||||
{ 1149, PT_SC, ucp_Phoenician },
|
||||
{ 1160, PT_PC, ucp_Pi },
|
||||
{ 1163, PT_PC, ucp_Po },
|
||||
{ 1166, PT_PC, ucp_Ps },
|
||||
{ 1169, PT_SC, ucp_Psalter_Pahlavi },
|
||||
{ 1185, PT_SC, ucp_Rejang },
|
||||
{ 1192, PT_SC, ucp_Runic },
|
||||
{ 1198, PT_GC, ucp_S },
|
||||
{ 1200, PT_SC, ucp_Samaritan },
|
||||
{ 1210, PT_SC, ucp_Saurashtra },
|
||||
{ 1221, PT_PC, ucp_Sc },
|
||||
{ 1224, PT_SC, ucp_Sharada },
|
||||
{ 1232, PT_SC, ucp_Shavian },
|
||||
{ 1240, PT_SC, ucp_Siddham },
|
||||
{ 1248, PT_SC, ucp_SignWriting },
|
||||
{ 1260, PT_SC, ucp_Sinhala },
|
||||
{ 1268, PT_PC, ucp_Sk },
|
||||
{ 1271, PT_PC, ucp_Sm },
|
||||
{ 1274, PT_PC, ucp_So },
|
||||
{ 1277, PT_SC, ucp_Sogdian },
|
||||
{ 1285, PT_SC, ucp_Sora_Sompeng },
|
||||
{ 1298, PT_SC, ucp_Soyombo },
|
||||
{ 1306, PT_SC, ucp_Sundanese },
|
||||
{ 1316, PT_SC, ucp_Syloti_Nagri },
|
||||
{ 1329, PT_SC, ucp_Syriac },
|
||||
{ 1336, PT_SC, ucp_Tagalog },
|
||||
{ 1344, PT_SC, ucp_Tagbanwa },
|
||||
{ 1353, PT_SC, ucp_Tai_Le },
|
||||
{ 1360, PT_SC, ucp_Tai_Tham },
|
||||
{ 1369, PT_SC, ucp_Tai_Viet },
|
||||
{ 1378, PT_SC, ucp_Takri },
|
||||
{ 1384, PT_SC, ucp_Tamil },
|
||||
{ 1390, PT_SC, ucp_Tangut },
|
||||
{ 1397, PT_SC, ucp_Telugu },
|
||||
{ 1404, PT_SC, ucp_Thaana },
|
||||
{ 1411, PT_SC, ucp_Thai },
|
||||
{ 1416, PT_SC, ucp_Tibetan },
|
||||
{ 1424, PT_SC, ucp_Tifinagh },
|
||||
{ 1433, PT_SC, ucp_Tirhuta },
|
||||
{ 1441, PT_SC, ucp_Ugaritic },
|
||||
{ 1450, PT_SC, ucp_Unknown },
|
||||
{ 1458, PT_SC, ucp_Vai },
|
||||
{ 1462, PT_SC, ucp_Warang_Citi },
|
||||
{ 1474, PT_ALNUM, 0 },
|
||||
{ 1478, PT_PXSPACE, 0 },
|
||||
{ 1482, PT_SPACE, 0 },
|
||||
{ 1486, PT_UCNC, 0 },
|
||||
{ 1490, PT_WORD, 0 },
|
||||
{ 1494, PT_SC, ucp_Yi },
|
||||
{ 1497, PT_GC, ucp_Z },
|
||||
{ 1499, PT_SC, ucp_Zanabazar_Square },
|
||||
{ 1516, PT_PC, ucp_Zl },
|
||||
{ 1519, PT_PC, ucp_Zp },
|
||||
{ 1522, PT_PC, ucp_Zs }
|
||||
{ 337, PT_SC, ucp_Elymaic },
|
||||
{ 345, PT_SC, ucp_Ethiopic },
|
||||
{ 354, PT_SC, ucp_Georgian },
|
||||
{ 363, PT_SC, ucp_Glagolitic },
|
||||
{ 374, PT_SC, ucp_Gothic },
|
||||
{ 381, PT_SC, ucp_Grantha },
|
||||
{ 389, PT_SC, ucp_Greek },
|
||||
{ 395, PT_SC, ucp_Gujarati },
|
||||
{ 404, PT_SC, ucp_Gunjala_Gondi },
|
||||
{ 418, PT_SC, ucp_Gurmukhi },
|
||||
{ 427, PT_SC, ucp_Han },
|
||||
{ 431, PT_SC, ucp_Hangul },
|
||||
{ 438, PT_SC, ucp_Hanifi_Rohingya },
|
||||
{ 454, PT_SC, ucp_Hanunoo },
|
||||
{ 462, PT_SC, ucp_Hatran },
|
||||
{ 469, PT_SC, ucp_Hebrew },
|
||||
{ 476, PT_SC, ucp_Hiragana },
|
||||
{ 485, PT_SC, ucp_Imperial_Aramaic },
|
||||
{ 502, PT_SC, ucp_Inherited },
|
||||
{ 512, PT_SC, ucp_Inscriptional_Pahlavi },
|
||||
{ 534, PT_SC, ucp_Inscriptional_Parthian },
|
||||
{ 557, PT_SC, ucp_Javanese },
|
||||
{ 566, PT_SC, ucp_Kaithi },
|
||||
{ 573, PT_SC, ucp_Kannada },
|
||||
{ 581, PT_SC, ucp_Katakana },
|
||||
{ 590, PT_SC, ucp_Kayah_Li },
|
||||
{ 599, PT_SC, ucp_Kharoshthi },
|
||||
{ 610, PT_SC, ucp_Khmer },
|
||||
{ 616, PT_SC, ucp_Khojki },
|
||||
{ 623, PT_SC, ucp_Khudawadi },
|
||||
{ 633, PT_GC, ucp_L },
|
||||
{ 635, PT_LAMP, 0 },
|
||||
{ 638, PT_SC, ucp_Lao },
|
||||
{ 642, PT_SC, ucp_Latin },
|
||||
{ 648, PT_SC, ucp_Lepcha },
|
||||
{ 655, PT_SC, ucp_Limbu },
|
||||
{ 661, PT_SC, ucp_Linear_A },
|
||||
{ 670, PT_SC, ucp_Linear_B },
|
||||
{ 679, PT_SC, ucp_Lisu },
|
||||
{ 684, PT_PC, ucp_Ll },
|
||||
{ 687, PT_PC, ucp_Lm },
|
||||
{ 690, PT_PC, ucp_Lo },
|
||||
{ 693, PT_PC, ucp_Lt },
|
||||
{ 696, PT_PC, ucp_Lu },
|
||||
{ 699, PT_SC, ucp_Lycian },
|
||||
{ 706, PT_SC, ucp_Lydian },
|
||||
{ 713, PT_GC, ucp_M },
|
||||
{ 715, PT_SC, ucp_Mahajani },
|
||||
{ 724, PT_SC, ucp_Makasar },
|
||||
{ 732, PT_SC, ucp_Malayalam },
|
||||
{ 742, PT_SC, ucp_Mandaic },
|
||||
{ 750, PT_SC, ucp_Manichaean },
|
||||
{ 761, PT_SC, ucp_Marchen },
|
||||
{ 769, PT_SC, ucp_Masaram_Gondi },
|
||||
{ 783, PT_PC, ucp_Mc },
|
||||
{ 786, PT_PC, ucp_Me },
|
||||
{ 789, PT_SC, ucp_Medefaidrin },
|
||||
{ 801, PT_SC, ucp_Meetei_Mayek },
|
||||
{ 814, PT_SC, ucp_Mende_Kikakui },
|
||||
{ 828, PT_SC, ucp_Meroitic_Cursive },
|
||||
{ 845, PT_SC, ucp_Meroitic_Hieroglyphs },
|
||||
{ 866, PT_SC, ucp_Miao },
|
||||
{ 871, PT_PC, ucp_Mn },
|
||||
{ 874, PT_SC, ucp_Modi },
|
||||
{ 879, PT_SC, ucp_Mongolian },
|
||||
{ 889, PT_SC, ucp_Mro },
|
||||
{ 893, PT_SC, ucp_Multani },
|
||||
{ 901, PT_SC, ucp_Myanmar },
|
||||
{ 909, PT_GC, ucp_N },
|
||||
{ 911, PT_SC, ucp_Nabataean },
|
||||
{ 921, PT_SC, ucp_Nandinagari },
|
||||
{ 933, PT_PC, ucp_Nd },
|
||||
{ 936, PT_SC, ucp_New_Tai_Lue },
|
||||
{ 948, PT_SC, ucp_Newa },
|
||||
{ 953, PT_SC, ucp_Nko },
|
||||
{ 957, PT_PC, ucp_Nl },
|
||||
{ 960, PT_PC, ucp_No },
|
||||
{ 963, PT_SC, ucp_Nushu },
|
||||
{ 969, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
|
||||
{ 992, PT_SC, ucp_Ogham },
|
||||
{ 998, PT_SC, ucp_Ol_Chiki },
|
||||
{ 1007, PT_SC, ucp_Old_Hungarian },
|
||||
{ 1021, PT_SC, ucp_Old_Italic },
|
||||
{ 1032, PT_SC, ucp_Old_North_Arabian },
|
||||
{ 1050, PT_SC, ucp_Old_Permic },
|
||||
{ 1061, PT_SC, ucp_Old_Persian },
|
||||
{ 1073, PT_SC, ucp_Old_Sogdian },
|
||||
{ 1085, PT_SC, ucp_Old_South_Arabian },
|
||||
{ 1103, PT_SC, ucp_Old_Turkic },
|
||||
{ 1114, PT_SC, ucp_Oriya },
|
||||
{ 1120, PT_SC, ucp_Osage },
|
||||
{ 1126, PT_SC, ucp_Osmanya },
|
||||
{ 1134, PT_GC, ucp_P },
|
||||
{ 1136, PT_SC, ucp_Pahawh_Hmong },
|
||||
{ 1149, PT_SC, ucp_Palmyrene },
|
||||
{ 1159, PT_SC, ucp_Pau_Cin_Hau },
|
||||
{ 1171, PT_PC, ucp_Pc },
|
||||
{ 1174, PT_PC, ucp_Pd },
|
||||
{ 1177, PT_PC, ucp_Pe },
|
||||
{ 1180, PT_PC, ucp_Pf },
|
||||
{ 1183, PT_SC, ucp_Phags_Pa },
|
||||
{ 1192, PT_SC, ucp_Phoenician },
|
||||
{ 1203, PT_PC, ucp_Pi },
|
||||
{ 1206, PT_PC, ucp_Po },
|
||||
{ 1209, PT_PC, ucp_Ps },
|
||||
{ 1212, PT_SC, ucp_Psalter_Pahlavi },
|
||||
{ 1228, PT_SC, ucp_Rejang },
|
||||
{ 1235, PT_SC, ucp_Runic },
|
||||
{ 1241, PT_GC, ucp_S },
|
||||
{ 1243, PT_SC, ucp_Samaritan },
|
||||
{ 1253, PT_SC, ucp_Saurashtra },
|
||||
{ 1264, PT_PC, ucp_Sc },
|
||||
{ 1267, PT_SC, ucp_Sharada },
|
||||
{ 1275, PT_SC, ucp_Shavian },
|
||||
{ 1283, PT_SC, ucp_Siddham },
|
||||
{ 1291, PT_SC, ucp_SignWriting },
|
||||
{ 1303, PT_SC, ucp_Sinhala },
|
||||
{ 1311, PT_PC, ucp_Sk },
|
||||
{ 1314, PT_PC, ucp_Sm },
|
||||
{ 1317, PT_PC, ucp_So },
|
||||
{ 1320, PT_SC, ucp_Sogdian },
|
||||
{ 1328, PT_SC, ucp_Sora_Sompeng },
|
||||
{ 1341, PT_SC, ucp_Soyombo },
|
||||
{ 1349, PT_SC, ucp_Sundanese },
|
||||
{ 1359, PT_SC, ucp_Syloti_Nagri },
|
||||
{ 1372, PT_SC, ucp_Syriac },
|
||||
{ 1379, PT_SC, ucp_Tagalog },
|
||||
{ 1387, PT_SC, ucp_Tagbanwa },
|
||||
{ 1396, PT_SC, ucp_Tai_Le },
|
||||
{ 1403, PT_SC, ucp_Tai_Tham },
|
||||
{ 1412, PT_SC, ucp_Tai_Viet },
|
||||
{ 1421, PT_SC, ucp_Takri },
|
||||
{ 1427, PT_SC, ucp_Tamil },
|
||||
{ 1433, PT_SC, ucp_Tangut },
|
||||
{ 1440, PT_SC, ucp_Telugu },
|
||||
{ 1447, PT_SC, ucp_Thaana },
|
||||
{ 1454, PT_SC, ucp_Thai },
|
||||
{ 1459, PT_SC, ucp_Tibetan },
|
||||
{ 1467, PT_SC, ucp_Tifinagh },
|
||||
{ 1476, PT_SC, ucp_Tirhuta },
|
||||
{ 1484, PT_SC, ucp_Ugaritic },
|
||||
{ 1493, PT_SC, ucp_Unknown },
|
||||
{ 1501, PT_SC, ucp_Vai },
|
||||
{ 1505, PT_SC, ucp_Wancho },
|
||||
{ 1512, PT_SC, ucp_Warang_Citi },
|
||||
{ 1524, PT_ALNUM, 0 },
|
||||
{ 1528, PT_PXSPACE, 0 },
|
||||
{ 1532, PT_SPACE, 0 },
|
||||
{ 1536, PT_UCNC, 0 },
|
||||
{ 1540, PT_WORD, 0 },
|
||||
{ 1544, PT_SC, ucp_Yi },
|
||||
{ 1547, PT_GC, ucp_Z },
|
||||
{ 1549, PT_SC, ucp_Zanabazar_Square },
|
||||
{ 1566, PT_PC, ucp_Zl },
|
||||
{ 1569, PT_PC, ucp_Zp },
|
||||
{ 1572, PT_PC, ucp_Zs }
|
||||
};
|
||||
|
||||
const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -281,7 +281,12 @@ enum {
|
|||
ucp_Makasar,
|
||||
ucp_Medefaidrin,
|
||||
ucp_Old_Sogdian,
|
||||
ucp_Sogdian
|
||||
ucp_Sogdian,
|
||||
/* New for Unicode 12.0.0 */
|
||||
ucp_Elymaic,
|
||||
ucp_Nandinagari,
|
||||
ucp_Nyiakeng_Puachue_Hmong,
|
||||
ucp_Wancho
|
||||
};
|
||||
|
||||
#endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */
|
||||
|
|
|
@ -214,6 +214,10 @@
|
|||
#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
|
||||
|
|
|
@ -118,10 +118,20 @@ static SLJIT_INLINE int get_map_jit_flag()
|
|||
if (map_jit_flag == -1) {
|
||||
struct utsname name;
|
||||
|
||||
map_jit_flag = 0;
|
||||
uname(&name);
|
||||
|
||||
/* Kernel version for 10.14.0 (Mojave) */
|
||||
map_jit_flag = (atoi(name.release) >= 18) ? MAP_JIT : 0;
|
||||
if (atoi(name.release) >= 18) {
|
||||
/* Only use MAP_JIT if a hardened runtime is used, because MAP_JIT is incompatible with fork(). */
|
||||
void *ptr = mmap(NULL, getpagesize(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
if (ptr == MAP_FAILED) {
|
||||
map_jit_flag = MAP_JIT;
|
||||
} else {
|
||||
munmap(ptr, getpagesize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return map_jit_flag;
|
||||
|
@ -137,6 +147,7 @@ static SLJIT_INLINE int get_map_jit_flag()
|
|||
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
||||
{
|
||||
void *retval;
|
||||
const int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||
|
||||
#ifdef MAP_ANON
|
||||
|
||||
|
@ -146,16 +157,25 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
|
|||
flags |= get_map_jit_flag();
|
||||
#endif
|
||||
|
||||
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, flags, -1, 0);
|
||||
retval = mmap(NULL, size, prot, flags, -1, 0);
|
||||
#else /* !MAP_ANON */
|
||||
if (dev_zero < 0) {
|
||||
if (open_dev_zero())
|
||||
return NULL;
|
||||
}
|
||||
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0);
|
||||
retval = mmap(NULL, size, prot, MAP_PRIVATE, dev_zero, 0);
|
||||
#endif /* MAP_ANON */
|
||||
|
||||
return (retval != MAP_FAILED) ? retval : NULL;
|
||||
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)
|
||||
|
|
|
@ -144,6 +144,7 @@
|
|||
#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)
|
||||
|
@ -521,6 +522,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -620,6 +627,30 @@ static SLJIT_INLINE sljit_s32 get_arg_count(sljit_s32 arg_types)
|
|||
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)
|
||||
|
@ -687,6 +718,19 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
|||
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))
|
||||
|
||||
|
@ -1905,6 +1949,21 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil
|
|||
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) \
|
||||
|
@ -2581,6 +2640,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
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);
|
||||
|
@ -2597,4 +2664,4 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
SLJIT_UNREACHABLE();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* !SLJIT_CONFIG_UNSUPPORTED */
|
||||
|
|
|
@ -348,13 +348,20 @@ struct sljit_label {
|
|||
struct sljit_jump {
|
||||
struct sljit_jump *next;
|
||||
sljit_uw addr;
|
||||
sljit_sw flags;
|
||||
sljit_uw flags;
|
||||
union {
|
||||
sljit_uw target;
|
||||
struct sljit_label* label;
|
||||
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;
|
||||
|
@ -366,10 +373,12 @@ struct sljit_compiler {
|
|||
|
||||
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;
|
||||
struct sljit_memory_fragment *buf;
|
||||
|
@ -1314,10 +1323,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
|
|||
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);
|
||||
|
||||
/* The constant can be changed runtime (see: sljit_set_const)
|
||||
/* 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. */
|
||||
|
|
|
@ -583,8 +583,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
sljit_uw *buf_end;
|
||||
sljit_uw size;
|
||||
sljit_uw word_count;
|
||||
sljit_uw next_addr;
|
||||
sljit_sw executable_offset;
|
||||
sljit_sw jump_addr;
|
||||
sljit_sw addr;
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
sljit_uw cpool_size;
|
||||
sljit_uw cpool_skip_alignment;
|
||||
|
@ -597,6 +598,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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));
|
||||
|
@ -625,11 +627,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
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);
|
||||
|
@ -669,35 +673,45 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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. */
|
||||
SLJIT_ASSERT(!label || label->size >= word_count);
|
||||
SLJIT_ASSERT(!jump || jump->addr >= word_count);
|
||||
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
|
||||
if (jump && jump->addr == word_count) {
|
||||
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;
|
||||
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;
|
||||
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) {
|
||||
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;
|
||||
const_->addr = (sljit_uw)code_ptr;
|
||||
#else
|
||||
const_->addr = (sljit_uw)(code_ptr - 1);
|
||||
const_->addr = (sljit_uw)(code_ptr - 1);
|
||||
#endif
|
||||
const_ = const_->next;
|
||||
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)
|
||||
|
@ -725,6 +739,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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);
|
||||
|
@ -755,15 +770,15 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
buf_ptr = (sljit_uw *)jump->addr;
|
||||
|
||||
if (jump->flags & PATCH_B) {
|
||||
jump_addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
|
||||
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 - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - jump_addr) >= -0x02000000);
|
||||
*buf_ptr |= (((sljit_sw)jump->u.label->addr - jump_addr) >> 2) & 0x00ffffff;
|
||||
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 - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - jump_addr) >= -0x02000000);
|
||||
*buf_ptr |= (((sljit_sw)jump->u.target - jump_addr) >> 2) & 0x00ffffff;
|
||||
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) {
|
||||
|
@ -813,6 +828,22 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
}
|
||||
#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;
|
||||
|
@ -2639,23 +2670,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
|
|||
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;
|
||||
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_);
|
||||
|
||||
reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
|
||||
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, reg, TMP_PC, 0), init_value));
|
||||
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, reg, init_value));
|
||||
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)
|
||||
|
@ -2663,6 +2694,33 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
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);
|
||||
|
|
|
@ -161,7 +161,7 @@ static SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm)
|
|||
inst[3] = MOVK | dst | ((new_imm >> 48) << 5) | (3 << 21);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
|
||||
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;
|
||||
|
@ -196,14 +196,14 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
|
|||
return 4;
|
||||
}
|
||||
|
||||
if (target_addr <= 0xffffffffl) {
|
||||
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 <= 0xffffffffffffl) {
|
||||
if (target_addr < 0x1000000000000l) {
|
||||
if (jump->flags & IS_COND)
|
||||
code_ptr[-5] -= (1 << 5);
|
||||
jump->flags |= PATCH_ABS48;
|
||||
|
@ -215,6 +215,22 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
|
|||
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;
|
||||
|
@ -223,6 +239,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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;
|
||||
|
@ -230,6 +247,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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));
|
||||
|
@ -241,34 +259,47 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
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++;
|
||||
/* These structures are ordered by their address. */
|
||||
SLJIT_ASSERT(!label || label->size >= word_count);
|
||||
SLJIT_ASSERT(!jump || jump->addr >= word_count);
|
||||
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
|
||||
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 (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 ++;
|
||||
|
@ -286,6 +317,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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;
|
||||
|
@ -323,6 +355,23 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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);
|
||||
|
@ -1947,6 +1996,28 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
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;
|
||||
|
|
|
@ -365,11 +365,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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));
|
||||
|
@ -381,34 +383,46 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
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++;
|
||||
/* These structures are ordered by their address. */
|
||||
SLJIT_ASSERT(!label || label->size >= half_count);
|
||||
SLJIT_ASSERT(!jump || jump->addr >= half_count);
|
||||
SLJIT_ASSERT(!const_ || const_->addr >= half_count);
|
||||
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 (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 ++;
|
||||
|
@ -426,6 +440,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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;
|
||||
|
@ -434,6 +449,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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);
|
||||
|
@ -2311,6 +2332,27 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
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;
|
||||
|
|
|
@ -425,6 +425,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
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);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
@ -435,6 +436,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
|
|
@ -449,6 +449,55 @@ static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_
|
|||
}
|
||||
#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;
|
||||
|
@ -457,12 +506,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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));
|
||||
|
@ -474,39 +525,54 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
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++;
|
||||
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) {
|
||||
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 (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);
|
||||
jump->addr = (sljit_uw)(code_ptr - 3);
|
||||
#else
|
||||
jump->addr = (sljit_uw)(code_ptr - 7);
|
||||
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) {
|
||||
/* Just recording the address. */
|
||||
const_->addr = (sljit_uw)code_ptr;
|
||||
const_ = const_->next;
|
||||
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 ++;
|
||||
|
@ -524,6 +590,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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;
|
||||
|
@ -571,6 +638,21 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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);
|
||||
|
@ -2157,7 +2239,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
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;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
|
||||
|
@ -2167,11 +2249,38 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -259,6 +259,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
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);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
@ -269,6 +270,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
|
|
@ -35,9 +35,6 @@
|
|||
#error "Must implement count leading zeroes"
|
||||
#endif
|
||||
|
||||
#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))
|
||||
|
||||
#define PUSH_RLDICR(reg, shift) \
|
||||
push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
|
||||
|
||||
|
|
|
@ -231,6 +231,9 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
|||
#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)
|
||||
{
|
||||
|
@ -324,6 +327,55 @@ keep_address:
|
|||
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;
|
||||
|
@ -332,12 +384,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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));
|
||||
|
@ -356,71 +410,87 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
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++;
|
||||
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)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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
jump = jump->next;
|
||||
}
|
||||
if (const_ && const_->addr == word_count) {
|
||||
const_->addr = (sljit_uw)code_ptr;
|
||||
const_ = const_->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 ++;
|
||||
|
@ -438,6 +508,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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
|
||||
|
@ -503,6 +575,21 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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);
|
||||
|
@ -2261,7 +2348,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
|
|||
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;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
|
||||
|
@ -2271,11 +2358,38 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -267,6 +267,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
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);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
@ -277,6 +278,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000));
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
|
|
@ -298,12 +298,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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));
|
||||
|
@ -315,40 +317,52 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
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++;
|
||||
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)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
||||
label->size = code_ptr - code;
|
||||
label = label->next;
|
||||
}
|
||||
if (jump && jump->addr == word_count) {
|
||||
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);
|
||||
jump->addr = (sljit_uw)(code_ptr - 3);
|
||||
#else
|
||||
jump->addr = (sljit_uw)(code_ptr - 6);
|
||||
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;
|
||||
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 ++;
|
||||
|
@ -366,6 +380,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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;
|
||||
|
@ -389,8 +404,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
/* Set the fields of immediate loads. */
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
buf_ptr[0] = (buf_ptr[0] & 0xffc00000) | ((addr >> 10) & 0x3fffff);
|
||||
buf_ptr[1] = (buf_ptr[1] & 0xfffffc00) | (addr & 0x3ff);
|
||||
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
|
||||
|
@ -398,6 +414,20 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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;
|
||||
|
@ -1465,8 +1495,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
|
||||
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_s32 reg;
|
||||
struct sljit_const *const_;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
|
||||
|
@ -1476,11 +1506,31 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -38,8 +38,10 @@ static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, s
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset)
|
||||
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++;
|
||||
|
|
|
@ -39,8 +39,10 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg,
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type)
|
||||
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. */
|
||||
|
@ -72,6 +74,56 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
|
|||
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)
|
||||
|
|
|
@ -428,13 +428,15 @@ static sljit_u8 get_jump_code(sljit_s32 type)
|
|||
}
|
||||
|
||||
#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_s32 type, sljit_sw executable_offset);
|
||||
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, sljit_s32 type);
|
||||
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_s32 type, sljit_sw executable_offset)
|
||||
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;
|
||||
|
||||
|
@ -447,7 +449,7 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code
|
|||
|
||||
#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, type);
|
||||
return generate_far_jump_code(jump, code_ptr);
|
||||
#endif
|
||||
|
||||
if (type == SLJIT_JUMP) {
|
||||
|
@ -497,6 +499,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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));
|
||||
|
@ -511,6 +514,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
label = compiler->labels;
|
||||
jump = compiler->jumps;
|
||||
const_ = compiler->consts;
|
||||
put_label = compiler->put_labels;
|
||||
executable_offset = SLJIT_EXEC_OFFSET(code);
|
||||
|
||||
do {
|
||||
|
@ -525,27 +529,38 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
buf_ptr += len;
|
||||
}
|
||||
else {
|
||||
if (*buf_ptr >= 2) {
|
||||
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, *buf_ptr - 2, executable_offset);
|
||||
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, *buf_ptr - 2, executable_offset);
|
||||
code_ptr = generate_far_jump_code(jump, code_ptr, executable_offset);
|
||||
#else
|
||||
code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2);
|
||||
code_ptr = generate_far_jump_code(jump, code_ptr);
|
||||
#endif
|
||||
}
|
||||
jump = jump->next;
|
||||
}
|
||||
else if (*buf_ptr == 0) {
|
||||
label->addr = ((sljit_uw)code_ptr) + executable_offset;
|
||||
label->size = code_ptr - code;
|
||||
label = label->next;
|
||||
}
|
||||
else { /* *buf_ptr is 1 */
|
||||
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++;
|
||||
}
|
||||
|
@ -557,6 +572,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
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) {
|
||||
|
@ -591,8 +608,24 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
jump = jump->next;
|
||||
}
|
||||
|
||||
/* Some space may be wasted because of short jumps. */
|
||||
SLJIT_ASSERT(code_ptr <= code + compiler->size);
|
||||
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;
|
||||
|
@ -2481,7 +2514,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
PTR_FAIL_IF_NULL(jump);
|
||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
set_jump(jump, compiler, (type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT));
|
||||
type &= 0xff;
|
||||
|
||||
/* Worst case size. */
|
||||
|
@ -2495,7 +2528,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
PTR_FAIL_IF_NULL(inst);
|
||||
|
||||
*inst++ = 0;
|
||||
*inst++ = type + 2;
|
||||
*inst++ = 1;
|
||||
return jump;
|
||||
}
|
||||
|
||||
|
@ -2513,7 +2546,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
|||
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);
|
||||
set_jump(jump, compiler, JUMP_ADDR | (type << TYPE_SHIFT));
|
||||
jump->u.target = srcw;
|
||||
|
||||
/* Worst case size. */
|
||||
|
@ -2527,7 +2560,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
|||
FAIL_IF_NULL(inst);
|
||||
|
||||
*inst++ = 0;
|
||||
*inst++ = type + 2;
|
||||
*inst++ = 1;
|
||||
}
|
||||
else {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
@ -2831,7 +2864,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!inst);
|
||||
|
||||
*inst++ = 0;
|
||||
*inst++ = 1;
|
||||
*inst++ = 2;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (dst & SLJIT_MEM)
|
||||
|
@ -2842,6 +2875,54 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
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);
|
||||
|
|
|
@ -154,7 +154,13 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void)
|
|||
#include "windows.h"
|
||||
#else
|
||||
/* Provides mmap function. */
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#ifndef MAP_ANON
|
||||
#ifdef MAP_ANONYMOUS
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#endif
|
||||
#endif
|
||||
/* For detecting the page size. */
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
From 676425e522e08eb0e7dfaacdac79a5de27542322 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Shaw <andy.shaw@qt.io>
|
||||
Date: Wed, 11 Dec 2019 10:51:22 +0100
|
||||
Subject: [PATCH 53/53] Fix CVE-2019-19244 in SQLite
|
||||
|
||||
Fixes: QTBUG-80635
|
||||
Change-Id: I718349e28ec76ea164dd50f2a985f2074dd6bdbd
|
||||
---
|
||||
src/3rdparty/sqlite/sqlite3.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
|
||||
index 8fd740b300..bd647ca1c2 100644
|
||||
--- a/src/3rdparty/sqlite/sqlite3.c
|
||||
+++ b/src/3rdparty/sqlite/sqlite3.c
|
||||
@@ -131679,6 +131679,7 @@ SQLITE_PRIVATE int sqlite3Select(
|
||||
*/
|
||||
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
||||
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
||||
+ && p->pWin==0
|
||||
){
|
||||
p->selFlags &= ~SF_Distinct;
|
||||
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
||||
--
|
||||
2.21.0 (Apple Git-122.2)
|
||||
|
|
@ -131679,6 +131679,7 @@ SQLITE_PRIVATE int sqlite3Select(
|
|||
*/
|
||||
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
||||
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
||||
&& p->pWin==0
|
||||
){
|
||||
p->selFlags &= ~SF_Distinct;
|
||||
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
||||
|
|
|
@ -1093,14 +1093,20 @@ Mozilla License) is included. The data is then also used in QNetworkCookieJar::v
|
|||
"label": "Windows System Libraries",
|
||||
"condition": "config.win32 && libs.advapi32 && libs.gdi32 && libs.kernel32 && libs.netapi32 && libs.ole32 && libs.shell32 && libs.uuid && libs.user32 && libs.winmm && libs.ws2_32"
|
||||
},
|
||||
"cborstream": {
|
||||
"label": "CBOR stream I/O",
|
||||
"purpose": "Provides support for reading and writing the CBOR binary format.
|
||||
"cborstreamreader": {
|
||||
"label": "CBOR stream reading",
|
||||
"purpose": "Provides support for reading the CBOR binary format.
|
||||
|
||||
Note that this is required for plugin loading. Qt GUI needs QPA plugins for basic operation.",
|
||||
"section": "Utilities",
|
||||
"output": [ "publicFeature" ]
|
||||
},
|
||||
"cborstreamwriter": {
|
||||
"label": "CBOR stream writing",
|
||||
"purpose": "Provides support for writing the CBOR binary format.",
|
||||
"section": "Utilities",
|
||||
"output": [ "publicFeature" ]
|
||||
},
|
||||
"binaryjson": {
|
||||
"label": "Binary JSON (deprecated)",
|
||||
"purpose": "Provides support for the deprecated binary JSON format.",
|
||||
|
|
|
@ -119,22 +119,6 @@ hash.insert("plenty", 2000);
|
|||
//! [9]
|
||||
|
||||
|
||||
//! [10]
|
||||
QList<int> values = hash.values("plenty");
|
||||
for (int i = 0; i < values.size(); ++i)
|
||||
cout << values.at(i) << Qt::endl;
|
||||
//! [10]
|
||||
|
||||
|
||||
//! [11]
|
||||
QHash<QString, int>::iterator i = hash.find("plenty");
|
||||
while (i != hash.end() && i.key() == "plenty") {
|
||||
cout << i.value() << Qt::endl;
|
||||
++i;
|
||||
}
|
||||
//! [11]
|
||||
|
||||
|
||||
//! [12]
|
||||
QHash<QString, int> hash;
|
||||
...
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
\include module-use.qdocinc using qt module
|
||||
\quotefile overview/using-qt-core.cmake
|
||||
|
||||
See also the \l[QtDoc]{Building with CMake} overview.
|
||||
See also the \l[QtDoc]{Build with CMake} overview.
|
||||
|
||||
\section2 Building with qmake
|
||||
|
||||
|
|
|
@ -189,13 +189,13 @@
|
|||
XML file to indicate a file should be most compressed, regardless of
|
||||
which algorithms \c rcc supports.
|
||||
|
||||
\li \c{zstd}: use the \l{Zstandard}{https://zstd.net} library to compress
|
||||
\li \c{zstd}: use the \l{https://zstd.net}{Zstandard} library to compress
|
||||
contents. Valid compression levels range from 1 to 19, 1 is least
|
||||
compression (least CPU time) and 19 is the most compression (most CPU
|
||||
time). The default level is 14. A special value of 0 tells the \c{zstd}
|
||||
library to choose an implementation-defined default.
|
||||
|
||||
\li \c{zlib}: use the \l{zlib}{https://zlib.net} library to compress
|
||||
\li \c{zlib}: use the \l{https://zlib.net}{zlib} library to compress
|
||||
contents. Valid compression levels range from 1 to 9, with 1the least
|
||||
compression (least CPU time) and 9 the most compression (most CPU time).
|
||||
The special value 0 means "no compression" and should not be used. The
|
||||
|
|
|
@ -815,13 +815,14 @@
|
|||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(__has_warning)
|
||||
# if __has_warning("-Wunused-private-field")
|
||||
# define Q_DECL_UNUSED_MEMBER Q_DECL_UNUSED
|
||||
# endif
|
||||
# endif
|
||||
#endif // Q_CC_CLANG && !Q_CC_INTEL && !Q_CC_MSVC
|
||||
|
||||
#endif // Q_CC_CLANG
|
||||
#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
|
||||
# ifndef Q_DECL_UNUSED
|
||||
# define Q_DECL_UNUSED __attribute__((__unused__))
|
||||
# endif
|
||||
# define Q_DECL_UNUSED_MEMBER Q_DECL_UNUSED
|
||||
#endif
|
||||
|
||||
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
|
||||
# define Q_COMPILER_RESTRICTED_VLA
|
||||
|
|
|
@ -75,7 +75,8 @@
|
|||
# define QT_FEATURE_alloca_malloc_h -1
|
||||
#endif
|
||||
#define QT_FEATURE_binaryjson -1
|
||||
#define QT_FEATURE_cborstream -1
|
||||
#define QT_FEATURE_cborstreamreader -1
|
||||
#define QT_FEATURE_cborstreamwriter 1
|
||||
#define QT_CRYPTOGRAPHICHASH_ONLY_SHA1
|
||||
#define QT_FEATURE_cxx11_random (__has_include(<random>) ? 1 : -1)
|
||||
#define QT_NO_DATASTREAM
|
||||
|
|
|
@ -137,7 +137,7 @@ QT_BEGIN_NAMESPACE
|
|||
\sa qToLittleEndian()
|
||||
*/
|
||||
/*!
|
||||
\fn template <typename T> T qFromLittleEndian(const void *src)
|
||||
\fn template <typename T> inline T qFromLittleEndian(const void *src)
|
||||
\since 4.3
|
||||
\relates <QtEndian>
|
||||
|
||||
|
@ -159,7 +159,7 @@ QT_BEGIN_NAMESPACE
|
|||
\sa qToLittleEndian()
|
||||
*/
|
||||
/*!
|
||||
\fn template <typename T> T qFromLittleEndian(T src)
|
||||
\fn template <typename T> inline T qFromLittleEndian(T src)
|
||||
\since 4.3
|
||||
\relates <QtEndian>
|
||||
\overload
|
||||
|
@ -171,7 +171,7 @@ QT_BEGIN_NAMESPACE
|
|||
unmodified.
|
||||
*/
|
||||
/*!
|
||||
\fn template <typename T> T qFromLittleEndian(const void *src, qsizetype count, void *dest)
|
||||
\fn template <typename T> inline T qFromLittleEndian(const void *src, qsizetype count, void *dest)
|
||||
\since 5.12
|
||||
\relates <QtEndian>
|
||||
|
||||
|
|
|
@ -4160,36 +4160,6 @@ bool qunsetenv(const char *varName)
|
|||
directive.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro QABS(n)
|
||||
\relates <QtGlobal>
|
||||
\obsolete
|
||||
|
||||
Use qAbs(\a n) instead.
|
||||
|
||||
\sa QMIN(), QMAX()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro QMIN(x, y)
|
||||
\relates <QtGlobal>
|
||||
\obsolete
|
||||
|
||||
Use qMin(\a x, \a y) instead.
|
||||
|
||||
\sa QMAX(), QABS()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro QMAX(x, y)
|
||||
\relates <QtGlobal>
|
||||
\obsolete
|
||||
|
||||
Use qMax(\a x, \a y) instead.
|
||||
|
||||
\sa QMIN(), QABS()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro const char *qPrintable(const QString &str)
|
||||
\relates <QtGlobal>
|
||||
|
|
|
@ -892,6 +892,10 @@ QT_WARNING_POP
|
|||
# define Q_DUMMY_COMPARISON_OPERATOR(C)
|
||||
#endif
|
||||
|
||||
QT_WARNING_PUSH
|
||||
// warning: noexcept-expression evaluates to ‘false’ because of a call to ‘void swap(..., ...)'
|
||||
QT_WARNING_DISABLE_GCC("-Wnoexcept")
|
||||
|
||||
namespace QtPrivate
|
||||
{
|
||||
namespace SwapExceptionTester { // insulate users from the "using std::swap" below
|
||||
|
@ -911,6 +915,8 @@ inline void qSwap(T &value1, T &value2)
|
|||
swap(value1, value2);
|
||||
}
|
||||
|
||||
QT_WARNING_POP
|
||||
|
||||
#if QT_DEPRECATED_SINCE(5, 0)
|
||||
Q_CORE_EXPORT QT_DEPRECATED void *qMalloc(size_t size) Q_ALLOC_SIZE(1);
|
||||
Q_CORE_EXPORT QT_DEPRECATED void qFree(void *ptr);
|
||||
|
@ -1214,8 +1220,10 @@ inline int qIntCast(float f) { return int(f); }
|
|||
/*
|
||||
Reentrant versions of basic rand() functions for random number generation
|
||||
*/
|
||||
Q_CORE_EXPORT void qsrand(uint seed);
|
||||
Q_CORE_EXPORT int qrand();
|
||||
#if QT_DEPRECATED_SINCE(5, 15)
|
||||
Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_5_15("use QRandomGenerator instead") void qsrand(uint seed);
|
||||
Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_5_15("use QRandomGenerator instead") int qrand();
|
||||
#endif
|
||||
|
||||
#define QT_MODULE(x)
|
||||
|
||||
|
|
|
@ -561,9 +561,39 @@ static QString getRelocatablePrefix()
|
|||
HMODULE hModule = getWindowsModuleHandle();
|
||||
const int kBufferSize = 4096;
|
||||
wchar_t buffer[kBufferSize];
|
||||
const int pathSize = GetModuleFileName(hModule, buffer, kBufferSize);
|
||||
if (pathSize > 0)
|
||||
prefixPath = prefixFromQtCoreLibraryHelper(QString::fromWCharArray(buffer, pathSize));
|
||||
DWORD pathSize = GetModuleFileName(hModule, buffer, kBufferSize);
|
||||
const QString qtCoreFilePath = QString::fromWCharArray(buffer, int(pathSize));
|
||||
const QString qtCoreDirPath = QFileInfo(qtCoreFilePath).absolutePath();
|
||||
pathSize = GetModuleFileName(NULL, buffer, kBufferSize);
|
||||
const QString exeDirPath = QFileInfo(QString::fromWCharArray(buffer, int(pathSize))).absolutePath();
|
||||
if (QFileInfo(exeDirPath) == QFileInfo(qtCoreDirPath)) {
|
||||
// QtCore DLL is next to the executable. This is either a windeployqt'ed executable or an
|
||||
// executable within the QT_HOST_BIN directory. We're detecting the latter case by checking
|
||||
// whether there's an import library corresponding to our QtCore DLL in PREFIX/lib.
|
||||
const QString libdir = QString::fromLatin1(
|
||||
qt_configure_strs + qt_configure_str_offsets[QLibraryInfo::LibrariesPath - 1]);
|
||||
const QLatin1Char slash('/');
|
||||
#if defined(Q_CC_MINGW)
|
||||
const QString implibPrefix = QStringLiteral("lib");
|
||||
const QString implibSuffix = QStringLiteral(".a");
|
||||
#else
|
||||
const QString implibPrefix;
|
||||
const QString implibSuffix = QStringLiteral(".lib");
|
||||
#endif
|
||||
const QString qtCoreImpLibFileName = implibPrefix
|
||||
+ QFileInfo(qtCoreFilePath).completeBaseName() + implibSuffix;
|
||||
const QString qtCoreImpLibPath = qtCoreDirPath
|
||||
+ slash + QLatin1String(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH)
|
||||
+ slash + libdir
|
||||
+ slash + qtCoreImpLibFileName;
|
||||
if (!QFileInfo::exists(qtCoreImpLibPath)) {
|
||||
// We did not find a corresponding import library and conclude that this is a
|
||||
// windeployqt'ed executable.
|
||||
return exeDirPath;
|
||||
}
|
||||
}
|
||||
if (!qtCoreFilePath.isEmpty())
|
||||
prefixPath = prefixFromQtCoreLibraryHelper(qtCoreFilePath);
|
||||
#else
|
||||
#error "The chosen platform / config does not support querying for a dynamic prefix."
|
||||
#endif
|
||||
|
|
|
@ -505,6 +505,7 @@ namespace Qt {
|
|||
AA_DontUseNativeMenuBar = 6,
|
||||
AA_MacDontSwapCtrlAndMeta = 7,
|
||||
AA_Use96Dpi = 8,
|
||||
AA_MSWindowsDisableVirtualKeyboard = 9,
|
||||
#if QT_DEPRECATED_SINCE(5, 14)
|
||||
AA_X11InitThreads Q_DECL_ENUMERATOR_DEPRECATED = 10,
|
||||
#endif
|
||||
|
|
|
@ -293,6 +293,12 @@
|
|||
This attribute must be set before QGuiApplication is constructed.
|
||||
This value was added in 5.13
|
||||
|
||||
\value AA_MSWindowsDisableVirtualKeyboard When this attribute is set,
|
||||
Windows' native on-screen virtual keyboard will not be shown
|
||||
automatically when a text input widget gains focus on a system
|
||||
without a physical keyboard.
|
||||
This value was added in 5.15
|
||||
|
||||
The following values are deprecated or obsolete:
|
||||
|
||||
\value AA_ImmediateWidgetCreation This attribute is no longer fully
|
||||
|
|
|
@ -299,6 +299,8 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
|
|||
|
||||
Returns the current OS type without constructing a QOperatingSystemVersion instance.
|
||||
|
||||
\since 5.10
|
||||
|
||||
\sa current()
|
||||
*/
|
||||
|
||||
|
|
|
@ -1295,7 +1295,7 @@ void qsrand(uint seed)
|
|||
\note This function is deprecated. In new applications, use
|
||||
QRandomGenerator instead.
|
||||
|
||||
\sa qrand(), QRandomGenerator
|
||||
\sa qsrand(), QRandomGenerator
|
||||
*/
|
||||
int qrand()
|
||||
{
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include <qelapsedtimer.h>
|
||||
#include <qfileinfo.h>
|
||||
#include <qrandom.h>
|
||||
#include <qregexp.h>
|
||||
#include <qwineventnotifier.h>
|
||||
#include <private/qsystemlibrary_p.h>
|
||||
#include <private/qthread_p.h>
|
||||
|
@ -398,7 +397,17 @@ static QString qt_create_commandline(const QString &program, const QStringList &
|
|||
for (int i=0; i<arguments.size(); ++i) {
|
||||
QString tmp = arguments.at(i);
|
||||
// Quotes are escaped and their preceding backslashes are doubled.
|
||||
tmp.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\""));
|
||||
int index = tmp.indexOf(QLatin1Char('"'));
|
||||
while (index >= 0) {
|
||||
// Escape quote
|
||||
tmp.insert(index++, QLatin1Char('\\'));
|
||||
// Double preceding backslashes (ignoring the one we just inserted)
|
||||
for (int i = index - 2 ; i >= 0 && tmp.at(i) == QLatin1Char('\\') ; --i) {
|
||||
tmp.insert(i, QLatin1Char('\\'));
|
||||
index++;
|
||||
}
|
||||
index = tmp.indexOf(QLatin1Char('"'), index + 1);
|
||||
}
|
||||
if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
|
||||
// The argument must not end with a \ since this would be interpreted
|
||||
// as escaping the quote -- rather put the \ behind the quote: e.g.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue