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:
Liang Qi 2020-01-04 15:32:34 +01:00
commit a503bf5470
363 changed files with 122259 additions and 8597 deletions

1331
LICENSE.QT-LICENSE-AGREEMENT Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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)

View File

@ -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"
}
],

View File

@ -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)

542
dist/changes-5.14.0 vendored Normal file
View File

@ -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.

View File

@ -1,39 +1,41 @@
macro.aacute.HTML = "&aacute;"
macro.Aring.HTML = "&Aring;"
macro.aring.HTML = "&aring;"
macro.Auml.HTML = "&Auml;"
macro.author = "\\b{Author:}"
macro.BR.HTML = "<br />"
macro.copyright.HTML = "&copy;"
macro.eacute.HTML = "&eacute;"
macro.gui = "\\b"
macro.HR.HTML = "<hr />"
macro.iacute.HTML = "&iacute;"
macro.key = "\\b"
macro.macos = "macOS"
macro.menu = "\\b"
macro.oslash.HTML = "&oslash;"
macro.ouml.HTML = "&ouml;"
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 = "&rarr;"
macro.reg.HTML = "<sup>&reg;</sup>"
macro.return = "Returns"
macro.starslash = "\\c{*/}"
macro.begincomment = "\\c{/*}"
macro.endcomment = "\\c{*/}"
macro.uuml.HTML = "&uuml;"
macro.mdash.HTML = "&mdash;"
macro.pi.HTML = "&Pi;"
macro.beginqdoc.HTML = "/*!"
macro.endqdoc.HTML = "*/"
macro.aacute.HTML = "&aacute;"
macro.Aring.HTML = "&Aring;"
macro.aring.HTML = "&aring;"
macro.Auml.HTML = "&Auml;"
macro.author = "\\b{Author:}"
macro.BR.HTML = "<br />"
macro.copyright.HTML = "&copy;"
macro.eacute.HTML = "&eacute;"
macro.gui = "\\b"
macro.HR.HTML = "<hr />"
macro.iacute.HTML = "&iacute;"
macro.key = "\\b"
macro.macos = "macOS"
macro.menu = "\\b"
macro.oslash.HTML = "&oslash;"
macro.ouml.HTML = "&ouml;"
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 = "&rarr;"
macro.reg.HTML = "<sup>&reg;</sup>"
macro.rego.DocBook = "\\sup{&#174;}"
macro.return = "Returns"
macro.starslash = "\\c{*/}"
macro.begincomment = "\\c{/*}"
macro.endcomment = "\\c{*/}"
macro.uuml.HTML = "&uuml;"
macro.mdash.HTML = "&mdash;"
macro.pi.HTML = "&Pi;"
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\">"

View File

@ -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()

View File

@ -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),

View File

@ -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) {

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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()));
}

View File

@ -361,7 +361,7 @@ QWidget *MainWindow::createImagesGroupBox()
QVBoxLayout *layout = new QVBoxLayout(imagesGroupBox);
layout->addWidget(imagesTable);
return imagesGroupBox;
//! [25]
//! [24]
}
//! [26]

View File

@ -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();

View File

@ -58,6 +58,7 @@
NorwegianWoodStyle::NorwegianWoodStyle() :
QProxyStyle(QStyleFactory::create("windows"))
{
setObjectName("NorwegianWood");
}
//! [0]

View File

@ -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]

View File

@ -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();

View File

@ -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]

View File

@ -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);
}

View File

@ -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());

View File

@ -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

View File

@ -7,4 +7,6 @@ CONFIG += bitcode reduce_exports shallow_bundle no_qt_rpath
INCLUDEPATH += $$PWD/uikit
DEFINES += GLES_SILENCE_DEPRECATION
include(mac.conf)

View File

@ -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
}

View File

@ -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

View File

@ -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 {

View File

@ -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)

View File

@ -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,&,&amp;,
1 ~= s,\',&apos;,
1 ~= s,\",&quot;,
1 ~= s,<,&lt;,
1 ~= s,>,&gt;,
return($$1)
}
load(resources_functions)
qtFlattenResources()

View File

@ -1,5 +1,21 @@
# http://www.w3.org/TR/xml/#syntax
defineReplace(xml_escape) {
1 ~= s,&,&amp;,
1 ~= s,\',&apos;,
1 ~= s,\",&quot;,
1 ~= s,<,&lt;,
1 ~= s,>,&gt;,
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)
}

View File

@ -0,0 +1,2 @@
load(default_pre)
load(emcc_ver)

View File

@ -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.")
}
}
}

View File

@ -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/

View File

@ -64,6 +64,8 @@
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
disableMainThreadChecker = "YES"
enableGPUFrameCaptureMode = "3"
enableGPUValidationMode = "1"
debugDocumentVersioning = "NO"
allowLocationSimulation = "YES">
<BuildableProductRunnable>

View File

@ -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 = \

View File

@ -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) $<

View File

@ -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 \

View File

@ -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 doesnt 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.

View File

@ -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");

View File

@ -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;");

View File

@ -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 \

View File

@ -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.",

View File

@ -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'.
//

View File

@ -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*)

View File

@ -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

View File

@ -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",

View File

@ -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_)

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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"
;

View File

@ -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 */ \

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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)

View File

@ -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 */

View File

@ -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;
}
}

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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)

View File

@ -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 */

View File

@ -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. */

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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))

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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++;

View File

@ -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)

View File

@ -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);

View File

@ -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>

View File

@ -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)

View File

@ -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);

View File

@ -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.",

View File

@ -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;
...

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()
*/

View File

@ -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()
{

View File

@ -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