Merge remote-tracking branch 'origin/5.5' into 5.6

Conflicts:
	qmake/doc/snippets/code/doc_src_qmake-manual.pro
	qmake/doc/src/qmake-manual.qdoc
	src/corelib/io/qstorageinfo_unix.cpp
	src/corelib/tools/qbytearray.cpp
	src/widgets/kernel/qwidgetwindow.cpp
	tests/auto/corelib/io/qprocess/tst_qprocess.cpp
	tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
	tests/auto/network/access/qnetworkreply/BLACKLIST

Change-Id: I9efcd7e1cce1c394eed425c43aa6fce7d2edf31c
This commit is contained in:
Liang Qi 2015-08-26 20:06:57 +02:00
commit afab1546a7
126 changed files with 2191 additions and 874 deletions

View File

@ -6,7 +6,7 @@
You may use, distribute and copy the Qt GUI Toolkit under the terms of
GNU Lesser General Public License version 3. That license references
the General Public License version 3, that is displayed below. Other
portions of the Qt Toolkit may be licensed directly other this license.
portions of the Qt Toolkit may be licensed directly under this license.
-------------------------------------------------------------------------

View File

@ -4,8 +4,8 @@
Contact: http://www.qt.io/licensing/
You may use, distribute and copy the Qt GUI Toolkit under the terms of
GNU Lesser General Public License version 3, which is displayed
below. This license makes reference to the version 3 of the GNU General
GNU Lesser General Public License version 3, which is displayed below.
This license makes reference to the version 3 of the GNU General
Public License, which you can find in the LICENSE.GPLv3 file.
-------------------------------------------------------------------------

View File

@ -140,7 +140,7 @@ greaterThan(MSC_VER, 1899) {
QMAKE_CFLAGS += -Zc:strictStrings
QMAKE_CFLAGS_WARN_ON += -w44456 -w44457 -w44458
QMAKE_CFLAGS_AVX2 = -arch:AVX2
QMAKE_CXXFLAGS += -Zc:strictStrings
QMAKE_CXXFLAGS += -Zc:strictStrings -Zc:throwingNew
QMAKE_CXXFLAGS_WARN_ON += -w44456 -w44457 -w44458 -wd4577
}

View File

@ -9,7 +9,8 @@
<Identity
Name=\"$${WINRT_MANIFEST.identity}\"
Publisher=\"$${WINRT_MANIFEST.publisherid}\"
Version=\"$${WINRT_MANIFEST.version}\" />
Version=\"$${WINRT_MANIFEST.version}\"
ProcessorArchitecture=\"$${WINRT_MANIFEST.architecture}\" />
<mp:PhoneIdentity PhoneProductId=\"$${WINRT_MANIFEST.identity}\" PhonePublisherId=\"$${WINRT_MANIFEST.phone_publisher_id}\"/>
@ -20,7 +21,7 @@
</Properties>
<Dependencies>
<TargetDeviceFamily Name=\"Windows.Universal\" MinVersion=\"10.0.10069.0\" MaxVersionTested=\"10.0.10069.0\" />
<TargetDeviceFamily Name=\"Windows.Universal\" MinVersion=\"10.0.10069.0\" MaxVersionTested=\"10.0.10069.0\" />$${WINRT_MANIFEST.dependencies}
</Dependencies>
<Resources>

View File

@ -41,6 +41,8 @@
<m2:SplashScreen Image=\"$${WINRT_MANIFEST.logo_620x300}\" />$${WINRT_MANIFEST.rotation_preference}
</m2:VisualElements>
</Application>
</Applications>$${WINRT_MANIFEST.capabilities}$${WINRT_MANIFEST.dependencies}
</Applications>$${WINRT_MANIFEST.capabilities}
<Dependencies>$${WINRT_MANIFEST.dependencies}
</Dependencies>
</Package>
<!-- Generated by qmake using the $$[QMAKE_XSPEC] mkspec. -->

View File

@ -42,6 +42,8 @@
<m3:SplashScreen Image=\"$${WINRT_MANIFEST.logo_480x800}\" />$${WINRT_MANIFEST.rotation_preference}
</m3:VisualElements>
</Application>
</Applications>$${WINRT_MANIFEST.capabilities}$${WINRT_MANIFEST.dependencies}
</Applications>$${WINRT_MANIFEST.capabilities}
<Dependencies>$${WINRT_MANIFEST.dependencies}
</Dependencies>
</Package>
<!-- Generated by qmake using the $$[QMAKE_XSPEC] mkspec. -->

View File

@ -0,0 +1,12 @@
*msvc2015 {
# Note that the order is important, ucrt(d) has to be first
# Otherwise the linker might use malloc from a different library
# but free_dbg() from the runtime, causing assert when deleting
# items from different heaps
CONFIG(debug, debug|release): \
QMAKE_LIBS = ucrtd.lib $$QMAKE_LIBS
else: \
QMAKE_LIBS = ucrt.lib $$QMAKE_LIBS
}
load(default_pre)

View File

@ -58,9 +58,11 @@
VCLIBS = Microsoft.VCLibs.$$replace(MSVC_VER, \\., ).00
winphone: VCLIBS = $${VCLIBS}.Phone
CONFIG(debug, debug|release): \
WINRT_MANIFEST.dependencies += $${VCLIBS}.Debug
VCLIBS = $${VCLIBS}.Debug
else: \
WINRT_MANIFEST.dependencies += $$VCLIBS
VCLIBS = $${VCLIBS}
contains(MSVC_VER, "14.0"): VCLIBS = "$${VCLIBS}\" MinVersion=\"14.0.0.0\" Publisher=\"CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
WINRT_MANIFEST.dependencies += $$VCLIBS
}
# Provide default values for required variables
@ -122,12 +124,11 @@
}
# Dependencies are given as a string list. The CRT dependency is added automatically above.
# For MSVC2015 the dependencies are added in conjunction with TargetDeviceFamily
WINRT_MANIFEST.dependencies = $$unique(WINRT_MANIFEST.dependencies)
!isEmpty(WINRT_MANIFEST.dependencies) {
MANIFEST_DEPENDENCIES += "<Dependencies>"
for(DEPENDENCY, WINRT_MANIFEST.dependencies): \
MANIFEST_DEPENDENCIES += " <PackageDependency Name=\"$$DEPENDENCY\" />"
MANIFEST_DEPENDENCIES += "</Dependencies>"
WINRT_MANIFEST.dependencies = $$join(MANIFEST_DEPENDENCIES, $$INDENT, $$INDENT)
}
@ -159,5 +160,13 @@
WINRT_MANIFEST.$${ICON_NAME} = assets/$$basename(ICON_FILE)
}
!contains(TEMPLATE, "vc.*") {
winrt_manifest_install.files = $$manifest_file.output
winrt_manifest_install.path = $$target.path
winrt_assets_install.files = $$BUILD_DIR/assets/*
winrt_assets_install.path = $$target.path/assets
INSTALLS += winrt_manifest_install winrt_assets_install
}
QMAKE_SUBSTITUTES += manifest_file
}

View File

@ -10,19 +10,9 @@ DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_APP ARM __ARM__ __arm__
QMAKE_CFLAGS += -FS
QMAKE_CXXFLAGS += -FS
QMAKE_LFLAGS += /MACHINE:ARM /NODEFAULTLIB:kernel32.lib
QMAKE_LFLAGS += /MACHINE:ARM
QMAKE_LIBS += windowscodecs.lib WindowsApp.lib runtimeobject.lib
# Note that the order is important, ucrt(d) has to be first
# Otherwise the linker might use malloc from a different library
# but free_dbg() from the runtime, causing assert when deleting
# items from different heaps
CONFIG(debug, debug|release) {
QMAKE_LIBS = ucrtd.lib $$QMAKE_LIBS
} else {
QMAKE_LIBS = ucrt.lib $$QMAKE_LIBS
}
QMAKE_LIBS += windowscodecs.lib WindowsApp.lib runtimeobject.lib kernel32.lib
VCPROJ_ARCH = ARM
MSVC_VER = 14.0

View File

@ -10,19 +10,9 @@ DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_APP X64 __X64__ __x64__
QMAKE_CFLAGS += -FS
QMAKE_CXXFLAGS += -FS
QMAKE_LFLAGS += /MACHINE:X64 /NODEFAULTLIB:kernel32.lib
QMAKE_LFLAGS += /MACHINE:X64
QMAKE_LIBS += windowscodecs.lib WindowsApp.lib runtimeobject.lib
# Note that the order is important, ucrt(d) has to be first
# Otherwise the linker might use malloc from a different library
# but free_dbg() from the runtime, causing assert when deleting
# items from different heaps
CONFIG(debug, debug|release) {
QMAKE_LIBS = ucrtd.lib $$QMAKE_LIBS
} else {
QMAKE_LIBS = ucrt.lib $$QMAKE_LIBS
}
QMAKE_LIBS += windowscodecs.lib WindowsApp.lib runtimeobject.lib kernel32.lib
VCPROJ_ARCH = x64
MSVC_VER = 14.0

View File

@ -10,19 +10,9 @@ DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_APP X86 __X86__ __x86__
QMAKE_CFLAGS += -FS
QMAKE_CXXFLAGS += -FS
QMAKE_LFLAGS += /SAFESEH /MACHINE:X86 /NODEFAULTLIB:kernel32.lib
QMAKE_LFLAGS += /SAFESEH /MACHINE:X86
QMAKE_LIBS += windowscodecs.lib WindowsApp.lib runtimeobject.lib
# Note that the order is important, ucrt(d) has to be first
# Otherwise the linker might use malloc from a different library
# but free_dbg() from the runtime, causing assert when deleting
# items from different heaps
CONFIG(debug, debug|release) {
QMAKE_LIBS = ucrtd.lib $$QMAKE_LIBS
} else {
QMAKE_LIBS = ucrt.lib $$QMAKE_LIBS
}
QMAKE_LIBS += windowscodecs.lib WindowsApp.lib runtimeobject.lib kernel32.lib
VCPROJ_ARCH = Win32
MSVC_VER = 14.0

View File

@ -977,3 +977,9 @@ VERSION_PE_HEADER = 1.2
RC_DEFINES += USE_MY_STUFF
#! [186]
#! [187]
win32-g++:contains(QMAKE_HOST.arch, x86_64):{
message("Host is 64bit")
...
}
#! [187]

View File

@ -1714,6 +1714,25 @@
See \l{Creating Frameworks} for more information about creating frameworks.
\target QMAKE_HOST
\section1 QMAKE_HOST
Provides information about the host machine running qmake.
For example, you can retrieve the host machine architecture from
\c{QMAKE_HOST.arch}.
\table
\header \li Keys \li Values
\row \li .arch \li Host architecture
\row \li .os \li Host OS
\row \li .cpu_count \li Number of available cpus
\row \li .name \li Host computer name
\row \li .version \li Host OS version number
\row \li .version_string \li Host OS version string
\endtable
\snippet code/doc_src_qmake-manual.pro 187
\target QMAKE_INCDIR
\section1 QMAKE_INCDIR

View File

@ -1478,7 +1478,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
else
warn_msg(WarnLogic, "Could not resolve Info.plist: '%s'. Check if QMAKE_INFO_PLIST points to a valid file.", plist.toLatin1().constData());
} else {
plist = specdir() + QDir::separator() + "Info.plist." + project->first("TEMPLATE");
plist = fileFixify(specdir() + QDir::separator() + "Info.plist." + project->first("TEMPLATE"), FileFixifyBackwards);
QFile plist_in_file(plist);
if (plist_in_file.open(QIODevice::ReadOnly)) {
QTextStream plist_in(&plist_in_file);
@ -1505,7 +1505,11 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
QTextStream plist_out(&plist_out_file);
plist_out << plist_in_text;
t << "\t\t\t\t" << writeSettings("INFOPLIST_FILE", "Info.plist") << ";\n";
} else {
warn_msg(WarnLogic, "Could not write Info.plist: '%s'.", plist_out_file.fileName().toLatin1().constData());
}
} else {
warn_msg(WarnLogic, "Could not open Info.plist: '%s'.", plist.toLatin1().constData());
}
}
}

View File

@ -817,7 +817,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << escapeDependencyPath(info_plist_out) << ": \n\t";
info_plist_out = escapeFilePath(info_plist_out);
if (!destdir.isEmpty())
t << mkdir_p_asstring(destdir, false) << "\n\t";
t << mkdir_p_asstring(destdir) << "\n\t";
ProStringList commonSedArgs;
if (!project->values("VERSION").isEmpty()) {
commonSedArgs << "-e \"s,@SHORT_VERSION@," << project->first("VER_MAJ") << "."
@ -839,6 +839,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
bundleIdentifier.chop(4);
if (bundleIdentifier.endsWith(".framework"))
bundleIdentifier.chop(10);
// replace invalid bundle id characters
bundleIdentifier.replace('_', '-');
commonSedArgs << "-e \"s,@BUNDLEIDENTIFIER@," << bundleIdentifier << ",g\" ";
if (!isFramework) {

View File

@ -643,7 +643,12 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
<< tagValue("DefaultLanguage", "en")
<< tagValue("AppContainerApplication", "true")
<< tagValue("ApplicationType", isWinPhone ? "Windows Phone" : "Windows Store")
<< tagValue("ApplicationTypeRevision", tool.SdkVersion == "10.0" ? "8.2" : tool.SdkVersion);
<< tagValue("ApplicationTypeRevision", tool.SdkVersion);
if (tool.SdkVersion == "10.0") {
const QString ucrtVersion = qgetenv("UCRTVERSION");
xml << tagValue("WindowsTargetPlatformVersion", ucrtVersion)
<< tagValue("WindowsTargetPlatformMinVersion", ucrtVersion);
}
}
xml << closetag();

View File

@ -190,19 +190,24 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
incDirs << vcInstallDir + QStringLiteral("include");
incDirs << vcInstallDir + QStringLiteral("atlmfc/include");
// ### Investigate why VS uses 10056 first
incDirs << kitDir + QStringLiteral("Include/10.0.10056.0/ucrt");
incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/ucrt");
incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/um");
incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/shared");
incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/winrt");
const QString crtVersion = qgetenv("UCRTVersion");
if (crtVersion.isEmpty()) {
fprintf(stderr, "Failed to access CRT version.\n");
return false;
}
const QString crtInclude = kitDir + QStringLiteral("Include/") + crtVersion;
const QString crtLib = kitDir + QStringLiteral("Lib/") + crtVersion;
incDirs << crtInclude + QStringLiteral("/ucrt");
incDirs << crtInclude + QStringLiteral("/um");
incDirs << crtInclude + QStringLiteral("/shared");
incDirs << crtInclude + QStringLiteral("/winrt");
libDirs << vcInstallDir + QStringLiteral("lib/store/") + compilerArch;
libDirs << vcInstallDir + QStringLiteral("atlmfc/lib") + compilerArch;
// ### Investigate why VS uses 10056 first
libDirs << kitDir + QStringLiteral("lib/10.0.10056.0/ucrt/") + arch;
libDirs << kitDir + QStringLiteral("lib/10.0.10069.0/ucrt/") + arch;
libDirs << kitDir + QStringLiteral("lib/10.0.10069.0/um/") + arch;
libDirs << crtLib + QStringLiteral("/ucrt/") + arch;
libDirs << crtLib + QStringLiteral("/um/") + arch;
} else if (isPhone) {
QString sdkDir = vcInstallDir;
if (!QDir(sdkDir).exists()) {

View File

@ -1307,7 +1307,8 @@ void VcprojGenerator::initDeploymentTool()
}
ProStringList dllPaths = project->values("QMAKE_DLL_PATHS");
// Only deploy Qt libs for shared build
if (!dllPaths.isEmpty()) {
if (!dllPaths.isEmpty() &&
!(conf.WinRT && project->first("MSVC_VER").toQString() == "14.0")) {
// FIXME: This code should actually resolve the libraries from all Qt modules.
ProStringList arg = project->values("QMAKE_LIBS") + project->values("QMAKE_LIBS_PRIVATE");
for (ProStringList::ConstIterator it = arg.constBegin(); it != arg.constEnd(); ++it) {

View File

@ -1,35 +0,0 @@
From 121e4d1ad09bdbfeb8a871d4f2c3ffe1acb8e2d6 Mon Sep 17 00:00:00 2001
From: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
Date: Tue, 30 Jun 2015 09:41:39 +0200
Subject: [PATCH] Re-fix X86 Wince builds.
eebb8de21ce4845866f15e444a4c78fc2cbb7f3f fixed the PCRE
build, but was accidentally overwritten by a subsequent
import of the PCRE tarball.
Now put the same patch also into patches/ so that we don't
forget it needs to be manually applied.
Change-Id: I93c2ee9c2e2dd1c48d391ce7e16d33208fb2cbbb
---
src/3rdparty/pcre/sljit/sljitNativeX86_common.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
index 22a163f..21b276f 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
@@ -273,7 +273,9 @@ static sljit_si cpu_has_sse2 = -1;
#endif
static sljit_si cpu_has_cmov = -1;
-#if defined(_MSC_VER) && _MSC_VER >= 1400
+#ifdef _WIN32_WCE
+#include <cmnintrin.h>
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
#include <intrin.h>
#endif
--
1.9.1

View File

@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE_MAJOR 8
#define PCRE_MINOR 37
#define PCRE_PRERELEASE
#define PCRE_DATE 2015-04-28
#define PCRE_MINOR 38
#define PCRE_PRERELEASE -RC1
#define PCRE_DATE 2015-05-03
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate

View File

@ -174,7 +174,7 @@ static const short int escapes[] = {
-ESC_Z, CHAR_LEFT_SQUARE_BRACKET,
CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET,
CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE,
CHAR_GRAVE_ACCENT, 7,
CHAR_GRAVE_ACCENT, ESC_a,
-ESC_b, 0,
-ESC_d, ESC_e,
ESC_f, 0,
@ -202,9 +202,9 @@ static const short int escapes[] = {
/* 68 */ 0, 0, '|', ',', '%', '_', '>', '?',
/* 70 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"',
/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0,
/* 80 */ 0, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0,
/* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0,
/* 90 */ 0, 0, -ESC_k, 'l', 0, ESC_n, 0, -ESC_p,
/* 90 */ 0, 0, -ESC_k, 0, 0, ESC_n, 0, -ESC_p,
/* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0,
/* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0,
/* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0,
@ -219,6 +219,12 @@ static const short int escapes[] = {
/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* F8 */ 0, 0, 0, 0, 0, 0, 0, 0
};
/* We also need a table of characters that may follow \c in an EBCDIC
environment for characters 0-31. */
static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
#endif
@ -458,7 +464,7 @@ static const char error_texts[] =
"range out of order in character class\0"
"nothing to repeat\0"
/* 10 */
"operand of unlimited repeat could match the empty string\0" /** DEAD **/
"internal error: invalid forward reference offset\0"
"internal error: unexpected repeat\0"
"unrecognized character after (? or (?-\0"
"POSIX named classes are supported only within a class\0"
@ -527,7 +533,11 @@ static const char error_texts[] =
"different names for subpatterns of the same number are not allowed\0"
"(*MARK) must have an argument\0"
"this version of PCRE is not compiled with Unicode property support\0"
#ifndef EBCDIC
"\\c must be followed by an ASCII character\0"
#else
"\\c must be followed by a letter or one of [\\]^_?\0"
#endif
"\\k is not followed by a braced, angle-bracketed, or quoted name\0"
/* 70 */
"internal error: unknown opcode in find_fixedlength()\0"
@ -1425,7 +1435,16 @@ else
c ^= 0x40;
#else /* EBCDIC coding */
if (c >= CHAR_a && c <= CHAR_z) c += 64;
c ^= 0xC0;
if (c == CHAR_QUESTION_MARK)
c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff;
else
{
for (i = 0; i < 32; i++)
{
if (c == ebcdic_escape_c[i]) break;
}
if (i < 32) c = i; else *errorcodeptr = ERR68;
}
#endif
break;
@ -1799,7 +1818,7 @@ for (;;)
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
do cc += GET(cc, 1); while (*cc == OP_ALT);
cc += PRIV(OP_lengths)[*cc];
cc += 1 + LINK_SIZE;
break;
/* Skip over things that don't match chars */
@ -2487,7 +2506,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
if (c == OP_BRA || c == OP_BRAPOS ||
c == OP_CBRA || c == OP_CBRAPOS ||
c == OP_ONCE || c == OP_ONCE_NC ||
c == OP_COND)
c == OP_COND || c == OP_SCOND)
{
BOOL empty_branch;
if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */
@ -3886,11 +3905,11 @@ didn't consider this to be a POSIX class. Likewise for [:1234:].
The problem in trying to be exactly like Perl is in the handling of escapes. We
have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX
class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code
below handles the special case of \], but does not try to do any other escape
processing. This makes it different from Perl for cases such as [:l\ower:]
where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize
"l\ower". This is a lesser evil than not diagnosing bad classes when Perl does,
I think.
below handles the special cases \\ and \], but does not try to do any other
escape processing. This makes it different from Perl for cases such as
[:l\ower:] where Perl recognizes it as the POSIX class "lower" but PCRE does
not recognize "l\ower". This is a lesser evil than not diagnosing bad classes
when Perl does, I think.
A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not.
It seems that the appearance of a nested POSIX class supersedes an apparent
@ -3917,21 +3936,16 @@ pcre_uchar terminator; /* Don't combine these lines; the Solaris cc */
terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */
for (++ptr; *ptr != CHAR_NULL; ptr++)
{
if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
if (*ptr == CHAR_BACKSLASH &&
(ptr[1] == CHAR_RIGHT_SQUARE_BRACKET ||
ptr[1] == CHAR_BACKSLASH))
ptr++;
else if (*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE;
else
else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) ||
*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE;
else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
{
if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
{
*endptr = ptr;
return TRUE;
}
if (*ptr == CHAR_LEFT_SQUARE_BRACKET &&
(ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
ptr[1] == CHAR_EQUALS_SIGN) &&
check_posix_syntax(ptr, endptr))
return FALSE;
*endptr = ptr;
return TRUE;
}
}
return FALSE;
@ -3985,11 +3999,12 @@ have their offsets adjusted. That one of the jobs of this function. Before it
is called, the partially compiled regex must be temporarily terminated with
OP_END.
This function has been extended with the possibility of forward references for
recursions and subroutine calls. It must also check the list of such references
for the group we are dealing with. If it finds that one of the recursions in
the current group is on this list, it adjusts the offset in the list, not the
value in the reference (which is a group number).
This function has been extended to cope with forward references for recursions
and subroutine calls. It must check the list of such references for the
group we are dealing with. If it finds that one of the recursions in the
current group is on this list, it does not adjust the value in the reference
(which is a group number). After the group has been scanned, all the offsets in
the forward reference list for the group are adjusted.
Arguments:
group points to the start of the group
@ -4005,29 +4020,21 @@ static void
adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd,
size_t save_hwm_offset)
{
int offset;
pcre_uchar *hc;
pcre_uchar *ptr = group;
while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL)
{
int offset;
pcre_uchar *hc;
/* See if this recursion is on the forward reference list. If so, adjust the
reference. */
for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm;
hc += LINK_SIZE)
{
offset = (int)GET(hc, 0);
if (cd->start_code + offset == ptr + 1)
{
PUT(hc, 0, offset + adjust);
break;
}
if (cd->start_code + offset == ptr + 1) break;
}
/* Otherwise, adjust the recursion offset if it's after the start of this
group. */
/* If we have not found this recursion on the forward reference list, adjust
the recursion's offset if it's after the start of this group. */
if (hc >= cd->hwm)
{
@ -4037,6 +4044,15 @@ while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL)
ptr += 1 + LINK_SIZE;
}
/* Now adjust all forward reference offsets for the group. */
for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm;
hc += LINK_SIZE)
{
offset = (int)GET(hc, 0);
PUT(hc, 0, offset + adjust);
}
}
@ -4465,7 +4481,7 @@ const pcre_uchar *tempptr;
const pcre_uchar *nestptr = NULL;
pcre_uchar *previous = NULL;
pcre_uchar *previous_callout = NULL;
size_t save_hwm_offset = 0;
size_t item_hwm_offset = 0;
pcre_uint8 classbits[32];
/* We can fish out the UTF-8 setting once and for all into a BOOL, but we
@ -4767,6 +4783,7 @@ for (;; ptr++)
zeroreqchar = reqchar;
zeroreqcharflags = reqcharflags;
previous = code;
item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY;
break;
@ -4818,6 +4835,7 @@ for (;; ptr++)
/* Handle a real character class. */
previous = code;
item_hwm_offset = cd->hwm - cd->start_workspace;
/* PCRE supports POSIX class stuff inside a class. Perl gives an error if
they are encountered at the top level, so we'll do that too. */
@ -5195,9 +5213,9 @@ for (;; ptr++)
cd, PRIV(vspace_list));
continue;
#ifdef SUPPORT_UCP
case ESC_p:
case ESC_P:
#ifdef SUPPORT_UCP
{
BOOL negated;
unsigned int ptype = 0, pdata = 0;
@ -5211,6 +5229,9 @@ for (;; ptr++)
class_has_8bitchar--; /* Undo! */
continue;
}
#else
*errorcodeptr = ERR45;
goto FAILED;
#endif
/* Unrecognized escapes are faulted if PCRE is running in its
strict mode. By default, for compatibility with Perl, they are
@ -5930,7 +5951,7 @@ for (;; ptr++)
{
register int i;
int len = (int)(code - previous);
size_t base_hwm_offset = save_hwm_offset;
size_t base_hwm_offset = item_hwm_offset;
pcre_uchar *bralink = NULL;
pcre_uchar *brazeroptr = NULL;
@ -5985,7 +6006,7 @@ for (;; ptr++)
if (repeat_max <= 1) /* Covers 0, 1, and unlimited */
{
*code = OP_END;
adjust_recurse(previous, 1, utf, cd, save_hwm_offset);
adjust_recurse(previous, 1, utf, cd, item_hwm_offset);
memmove(previous + 1, previous, IN_UCHARS(len));
code++;
if (repeat_max == 0)
@ -6009,7 +6030,7 @@ for (;; ptr++)
{
int offset;
*code = OP_END;
adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm_offset);
adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, item_hwm_offset);
memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len));
code += 2 + LINK_SIZE;
*previous++ = OP_BRAZERO + repeat_type;
@ -6254,6 +6275,12 @@ for (;; ptr++)
while (*scode == OP_ALT);
}
/* A conditional group with only one branch has an implicit empty
alternative branch. */
if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT)
*bracode = OP_SCOND;
/* Handle possessive quantifiers. */
if (possessive_quantifier)
@ -6267,11 +6294,11 @@ for (;; ptr++)
{
int nlen = (int)(code - bracode);
*code = OP_END;
adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, item_hwm_offset);
memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen));
code += 1 + LINK_SIZE;
nlen += 1 + LINK_SIZE;
*bracode = OP_BRAPOS;
*bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS;
*code++ = OP_KETRPOS;
PUTINC(code, 0, nlen);
PUT(bracode, 1, nlen);
@ -6401,7 +6428,7 @@ for (;; ptr++)
else
{
*code = OP_END;
adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset);
memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
code += 1 + LINK_SIZE;
len += 1 + LINK_SIZE;
@ -6450,7 +6477,7 @@ for (;; ptr++)
default:
*code = OP_END;
adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset);
memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
code += 1 + LINK_SIZE;
len += 1 + LINK_SIZE;
@ -6623,7 +6650,7 @@ for (;; ptr++)
newoptions = options;
skipbytes = 0;
bravalue = OP_CBRA;
save_hwm_offset = cd->hwm - cd->start_workspace;
item_hwm_offset = cd->hwm - cd->start_workspace;
reset_bracount = FALSE;
/* Deal with the extended parentheses; all are introduced by '?', and the
@ -6641,6 +6668,7 @@ for (;; ptr++)
/* ------------------------------------------------------------ */
case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */
reset_bracount = TRUE;
cd->dupgroups = TRUE; /* Record (?| encountered */
/* Fall through */
/* ------------------------------------------------------------ */
@ -6741,6 +6769,12 @@ for (;; ptr++)
{
while (IS_DIGIT(*ptr))
{
if (recno > INT_MAX / 10 - 1) /* Integer overflow */
{
while (IS_DIGIT(*ptr)) ptr++;
*errorcodeptr = ERR61;
goto FAILED;
}
recno = recno * 10 + (int)(*ptr - CHAR_0);
ptr++;
}
@ -6769,7 +6803,7 @@ for (;; ptr++)
ptr++;
}
namelen = (int)(ptr - name);
if (lengthptr != NULL) *lengthptr += IMM2_SIZE;
if (lengthptr != NULL) skipbytes += IMM2_SIZE;
}
/* Check the terminator */
@ -6875,6 +6909,11 @@ for (;; ptr++)
*errorcodeptr = ERR15;
goto FAILED;
}
if (recno > INT_MAX / 10 - 1) /* Integer overflow */
{
*errorcodeptr = ERR61;
goto FAILED;
}
recno = recno * 10 + name[i] - CHAR_0;
}
if (recno == 0) recno = RREF_ANY;
@ -7151,7 +7190,8 @@ for (;; ptr++)
if (lengthptr != NULL)
{
named_group *ng;
recno = 0;
if (namelen == 0)
{
*errorcodeptr = ERR62;
@ -7168,20 +7208,6 @@ for (;; ptr++)
goto FAILED;
}
/* The name table does not exist in the first pass; instead we must
scan the list of names encountered so far in order to get the
number. If the name is not found, set the value to 0 for a forward
reference. */
ng = cd->named_groups;
for (i = 0; i < cd->names_found; i++, ng++)
{
if (namelen == ng->length &&
STRNCMP_UC_UC(name, ng->name, namelen) == 0)
break;
}
recno = (i < cd->names_found)? ng->number : 0;
/* Count named back references. */
if (!is_recurse) cd->namedrefcount++;
@ -7191,6 +7217,56 @@ for (;; ptr++)
16-bit data item. */
*lengthptr += IMM2_SIZE;
/* If this is a forward reference and we are within a (?|...) group,
the reference may end up as the number of a group which we are
currently inside, that is, it could be a recursive reference. In the
real compile this will be picked up and the reference wrapped with
OP_ONCE to make it atomic, so we must space in case this occurs. */
/* In fact, this can happen for a non-forward reference because
another group with the same number might be created later. This
issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance
only mode, we finesse the bug by allowing more memory always. */
*lengthptr += 2 + 2*LINK_SIZE;
/* It is even worse than that. The current reference may be to an
existing named group with a different number (so apparently not
recursive) but which later on is also attached to a group with the
current number. This can only happen if $(| has been previous
encountered. In that case, we allow yet more memory, just in case.
(Again, this is fixed "properly" in PCRE2. */
if (cd->dupgroups) *lengthptr += 4 + 4*LINK_SIZE;
/* Otherwise, check for recursion here. The name table does not exist
in the first pass; instead we must scan the list of names encountered
so far in order to get the number. If the name is not found, leave
the value of recno as 0 for a forward reference. */
else
{
ng = cd->named_groups;
for (i = 0; i < cd->names_found; i++, ng++)
{
if (namelen == ng->length &&
STRNCMP_UC_UC(name, ng->name, namelen) == 0)
{
open_capitem *oc;
recno = ng->number;
if (is_recurse) break;
for (oc = cd->open_caps; oc != NULL; oc = oc->next)
{
if (oc->number == recno)
{
oc->flag = TRUE;
break;
}
}
}
}
}
}
/* In the real compile, search the name table. We check the name
@ -7237,8 +7313,6 @@ for (;; ptr++)
for (i++; i < cd->names_found; i++)
{
if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break;
count++;
cslot += cd->name_entry_size;
}
@ -7247,6 +7321,7 @@ for (;; ptr++)
{
if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
previous = code;
item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((options & PCRE_CASELESS) != 0)? OP_DNREFI : OP_DNREF;
PUT2INC(code, 0, index);
PUT2INC(code, 0, count);
@ -7284,9 +7359,14 @@ for (;; ptr++)
/* ------------------------------------------------------------ */
case CHAR_R: /* Recursion */
ptr++; /* Same as (?0) */
/* Fall through */
case CHAR_R: /* Recursion, same as (?0) */
recno = 0;
if (*(++ptr) != CHAR_RIGHT_PARENTHESIS)
{
*errorcodeptr = ERR29;
goto FAILED;
}
goto HANDLE_RECURSION;
/* ------------------------------------------------------------ */
@ -7323,7 +7403,15 @@ for (;; ptr++)
recno = 0;
while(IS_DIGIT(*ptr))
{
if (recno > INT_MAX / 10 - 1) /* Integer overflow */
{
while (IS_DIGIT(*ptr)) ptr++;
*errorcodeptr = ERR61;
goto FAILED;
}
recno = recno * 10 + *ptr++ - CHAR_0;
}
if (*ptr != (pcre_uchar)terminator)
{
@ -7360,6 +7448,7 @@ for (;; ptr++)
HANDLE_RECURSION:
previous = code;
item_hwm_offset = cd->hwm - cd->start_workspace;
called = cd->start_code;
/* When we are actually compiling, find the bracket that is being
@ -7561,7 +7650,11 @@ for (;; ptr++)
previous = NULL;
cd->iscondassert = FALSE;
}
else previous = code;
else
{
previous = code;
item_hwm_offset = cd->hwm - cd->start_workspace;
}
*code = bravalue;
tempcode = code;
@ -7809,7 +7902,7 @@ for (;; ptr++)
const pcre_uchar *p;
pcre_uint32 cf;
save_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */
item_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */
terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE;
@ -7838,7 +7931,7 @@ for (;; ptr++)
if (*p != (pcre_uchar)terminator)
{
*errorcodeptr = ERR57;
break;
goto FAILED;
}
ptr++;
goto HANDLE_NUMERICAL_RECURSION;
@ -7853,7 +7946,7 @@ for (;; ptr++)
ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET))
{
*errorcodeptr = ERR69;
break;
goto FAILED;
}
is_recurse = FALSE;
terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
@ -7877,6 +7970,7 @@ for (;; ptr++)
HANDLE_REFERENCE:
if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
previous = code;
item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF;
PUT2INC(code, 0, recno);
cd->backref_map |= (recno < 32)? (1 << recno) : 1;
@ -7906,6 +8000,7 @@ for (;; ptr++)
if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr))
goto FAILED;
previous = code;
item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((escape == ESC_p) != negated)? OP_PROP : OP_NOTPROP;
*code++ = ptype;
*code++ = pdata;
@ -7946,6 +8041,7 @@ for (;; ptr++)
{
previous = (escape > ESC_b && escape < ESC_Z)? code : NULL;
item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = (!utf && escape == ESC_C)? OP_ALLANY : escape;
}
}
@ -7989,6 +8085,7 @@ for (;; ptr++)
ONE_CHAR:
previous = code;
item_hwm_offset = cd->hwm - cd->start_workspace;
/* For caseless UTF-8 mode when UCP support is available, check whether
this character has more than one other case. If so, generate a special
@ -9164,6 +9261,7 @@ cd->names_found = 0;
cd->name_entry_size = 0;
cd->name_table = NULL;
cd->dupnames = FALSE;
cd->dupgroups = FALSE;
cd->namedrefcount = 0;
cd->start_code = cworkspace;
cd->hwm = cworkspace;
@ -9198,7 +9296,7 @@ if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN;
DPRINTF(("end pre-compile: length=%d workspace=%d\n", length,
(int)(cd->hwm - cworkspace)));
if (length > MAX_PATTERN_SIZE)
{
errorcode = ERR20;
@ -9336,6 +9434,16 @@ if (cd->hwm > cd->start_workspace)
int offset, recno;
cd->hwm -= LINK_SIZE;
offset = GET(cd->hwm, 0);
/* Check that the hwm handling hasn't gone wrong. This whole area is
rewritten in PCRE2 because there are some obscure cases. */
if (offset == 0 || codestart[offset-1] != OP_RECURSE)
{
errorcode = ERR10;
break;
}
recno = GET(codestart, offset);
if (recno != prev_recno)
{
@ -9366,7 +9474,7 @@ used in this code because at least one compiler gives a warning about loss of
"const" attribute if the cast (pcre_uchar *)codestart is used directly in the
function call. */
if ((options & PCRE_NO_AUTO_POSSESS) == 0)
if (errorcode == 0 && (options & PCRE_NO_AUTO_POSSESS) == 0)
{
pcre_uchar *temp = (pcre_uchar *)codestart;
auto_possessify(temp, utf, cd);
@ -9380,7 +9488,7 @@ OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The
exceptional ones forgo this. We scan the pattern to check that they are fixed
length, and set their lengths. */
if (cd->check_lookbehind)
if (errorcode == 0 && cd->check_lookbehind)
{
pcre_uchar *cc = (pcre_uchar *)codestart;
@ -9593,4 +9701,3 @@ return (pcre32 *)re;
}
/* End of pcre_compile.c */

View File

@ -6685,7 +6685,8 @@ if (md->offset_vector != NULL)
register int *iend = iptr - re->top_bracket;
if (iend < md->offset_vector + 2) iend = md->offset_vector + 2;
while (--iptr >= iend) *iptr = -1;
md->offset_vector[0] = md->offset_vector[1] = -1;
if (offsetcount > 0) md->offset_vector[0] = -1;
if (offsetcount > 1) md->offset_vector[1] = -1;
}
/* Set up the first character to match, if available. The first_char value is

View File

@ -984,7 +984,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */
#ifndef EBCDIC
#define HSPACE_LIST \
CHAR_HT, CHAR_SPACE, 0xa0, \
CHAR_HT, CHAR_SPACE, CHAR_NBSP, \
0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \
0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \
NOTACHAR
@ -1010,7 +1010,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */
#define HSPACE_BYTE_CASES \
case CHAR_HT: \
case CHAR_SPACE: \
case 0xa0 /* NBSP */
case CHAR_NBSP
#define HSPACE_CASES \
HSPACE_BYTE_CASES: \
@ -1037,11 +1037,12 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */
/* ------ EBCDIC environments ------ */
#else
#define HSPACE_LIST CHAR_HT, CHAR_SPACE
#define HSPACE_LIST CHAR_HT, CHAR_SPACE, CHAR_NBSP, NOTACHAR
#define HSPACE_BYTE_CASES \
case CHAR_HT: \
case CHAR_SPACE
case CHAR_SPACE: \
case CHAR_NBSP
#define HSPACE_CASES HSPACE_BYTE_CASES
@ -1215,6 +1216,7 @@ same code point. */
#define CHAR_ESC '\047'
#define CHAR_DEL '\007'
#define CHAR_NBSP '\x41'
#define STR_ESC "\047"
#define STR_DEL "\007"
@ -1229,6 +1231,7 @@ a positive value. */
#define CHAR_NEL ((unsigned char)'\x85')
#define CHAR_ESC '\033'
#define CHAR_DEL '\177'
#define CHAR_NBSP ((unsigned char)'\xa0')
#define STR_LF "\n"
#define STR_NL STR_LF
@ -1606,6 +1609,7 @@ only. */
#define CHAR_VERTICAL_LINE '\174'
#define CHAR_RIGHT_CURLY_BRACKET '\175'
#define CHAR_TILDE '\176'
#define CHAR_NBSP ((unsigned char)'\xa0')
#define STR_HT "\011"
#define STR_VT "\013"
@ -1762,6 +1766,10 @@ only. */
/* Escape items that are just an encoding of a particular data value. */
#ifndef ESC_a
#define ESC_a CHAR_BEL
#endif
#ifndef ESC_e
#define ESC_e CHAR_ESC
#endif
@ -2446,6 +2454,7 @@ typedef struct compile_data {
BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
BOOL check_lookbehind; /* Lookbehinds need later checking */
BOOL dupnames; /* Duplicate names exist */
BOOL dupgroups; /* Duplicate groups exist: (?| found */
BOOL iscondassert; /* Next assert is a condition */
int nltype; /* Newline type */
int nllen; /* Newline string length */

View File

@ -1064,6 +1064,7 @@ pcre_uchar *alternative;
pcre_uchar *end = NULL;
int private_data_ptr = *private_data_start;
int space, size, bracketlen;
BOOL repeat_check = TRUE;
while (cc < ccend)
{
@ -1071,9 +1072,10 @@ while (cc < ccend)
size = 0;
bracketlen = 0;
if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE)
return;
break;
if (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)
if (repeat_check && (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND))
{
if (detect_repeat(common, cc))
{
/* These brackets are converted to repeats, so no global
@ -1081,6 +1083,8 @@ while (cc < ccend)
if (cc >= end)
end = bracketend(cc);
}
}
repeat_check = TRUE;
switch(*cc)
{
@ -1136,6 +1140,13 @@ while (cc < ccend)
bracketlen = 1 + LINK_SIZE + IMM2_SIZE;
break;
case OP_BRAZERO:
case OP_BRAMINZERO:
case OP_BRAPOSZERO:
repeat_check = FALSE;
size = 1;
break;
CASE_ITERATOR_PRIVATE_DATA_1
space = 1;
size = -2;
@ -1162,12 +1173,17 @@ while (cc < ccend)
size = 1;
break;
CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
case OP_TYPEUPTO:
if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI)
space = 2;
size = 1 + IMM2_SIZE;
break;
case OP_TYPEMINUPTO:
space = 2;
size = 1 + IMM2_SIZE;
break;
case OP_CLASS:
case OP_NCLASS:
size += 1 + 32 / sizeof(pcre_uchar);
@ -1316,6 +1332,13 @@ while (cc < ccend)
cc += 1 + LINK_SIZE + IMM2_SIZE;
break;
case OP_THEN:
stack_restore = TRUE;
if (common->control_head_ptr != 0)
*needs_control_head = TRUE;
cc ++;
break;
default:
stack_restore = TRUE;
/* Fall through. */
@ -2220,6 +2243,7 @@ while (current != NULL)
SLJIT_ASSERT_STOP();
break;
}
SLJIT_ASSERT(current > (sljit_sw*)current[-1]);
current = (sljit_sw*)current[-1];
}
return -1;
@ -3209,7 +3233,7 @@ bytes[len] = byte;
bytes[0] = len;
}
static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars)
static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars, pcre_uint32 *rec_count)
{
/* Recursive function, which scans prefix literals. */
BOOL last, any, caseless;
@ -3227,9 +3251,14 @@ pcre_uchar othercase[1];
repeat = 1;
while (TRUE)
{
if (*rec_count == 0)
return 0;
(*rec_count)--;
last = TRUE;
any = FALSE;
caseless = FALSE;
switch (*cc)
{
case OP_CHARI:
@ -3291,7 +3320,7 @@ while (TRUE)
#ifdef SUPPORT_UTF
if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
#endif
max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars);
max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars, rec_count);
if (max_chars == 0)
return consumed;
last = FALSE;
@ -3314,7 +3343,7 @@ while (TRUE)
alternative = cc + GET(cc, 1);
while (*alternative == OP_ALT)
{
max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars);
max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars, rec_count);
if (max_chars == 0)
return consumed;
alternative += GET(alternative, 1);
@ -3556,6 +3585,7 @@ int i, max, from;
int range_right = -1, range_len = 3 - 1;
sljit_ub *update_table = NULL;
BOOL in_range;
pcre_uint32 rec_count;
for (i = 0; i < MAX_N_CHARS; i++)
{
@ -3564,7 +3594,8 @@ for (i = 0; i < MAX_N_CHARS; i++)
bytes[i * MAX_N_BYTES] = 0;
}
max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS);
rec_count = 10000;
max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS, &rec_count);
if (max <= 1)
return FALSE;
@ -7665,6 +7696,10 @@ while (*cc != OP_KETRPOS)
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
}
/* Even if the match is empty, we need to reset the control head. */
if (needs_control_head)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));
if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));
@ -7692,6 +7727,10 @@ while (*cc != OP_KETRPOS)
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw), STR_PTR, 0);
}
/* Even if the match is empty, we need to reset the control head. */
if (needs_control_head)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));
if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));
@ -7704,9 +7743,6 @@ while (*cc != OP_KETRPOS)
}
}
if (needs_control_head)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));
JUMPTO(SLJIT_JUMP, loop);
flush_stubs(common);
@ -9648,6 +9684,7 @@ set_jumps(common->currententry->calls, common->currententry->entry);
sljit_emit_fast_enter(compiler, TMP2, 0);
allocate_stack(common, private_data_size + framesize + alternativesize);
count_match(common);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0);
copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head);
if (needs_control_head)
@ -9992,6 +10029,7 @@ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match));
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0);
if (mode == JIT_PARTIAL_SOFT_COMPILE)

View File

@ -71,6 +71,7 @@ Arguments:
startcode pointer to start of the whole pattern's code
options the compiling options
recurses chain of recurse_check to catch mutual recursion
countptr pointer to call count (to catch over complexity)
Returns: the minimum length
-1 if \C in UTF-8 mode or (*ACCEPT) was encountered
@ -80,7 +81,8 @@ Returns: the minimum length
static int
find_minlength(const REAL_PCRE *re, const pcre_uchar *code,
const pcre_uchar *startcode, int options, recurse_check *recurses)
const pcre_uchar *startcode, int options, recurse_check *recurses,
int *countptr)
{
int length = -1;
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
@ -90,6 +92,8 @@ recurse_check this_recurse;
register int branchlength = 0;
register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE;
if ((*countptr)++ > 1000) return -1; /* too complex */
if (*code == OP_CBRA || *code == OP_SCBRA ||
*code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE;
@ -131,7 +135,7 @@ for (;;)
case OP_SBRAPOS:
case OP_ONCE:
case OP_ONCE_NC:
d = find_minlength(re, cc, startcode, options, recurses);
d = find_minlength(re, cc, startcode, options, recurses, countptr);
if (d < 0) return d;
branchlength += d;
do cc += GET(cc, 1); while (*cc == OP_ALT);
@ -415,7 +419,8 @@ for (;;)
int dd;
this_recurse.prev = recurses;
this_recurse.group = cs;
dd = find_minlength(re, cs, startcode, options, &this_recurse);
dd = find_minlength(re, cs, startcode, options, &this_recurse,
countptr);
if (dd < d) d = dd;
}
}
@ -451,7 +456,8 @@ for (;;)
{
this_recurse.prev = recurses;
this_recurse.group = cs;
d = find_minlength(re, cs, startcode, options, &this_recurse);
d = find_minlength(re, cs, startcode, options, &this_recurse,
countptr);
}
}
}
@ -514,7 +520,7 @@ for (;;)
this_recurse.prev = recurses;
this_recurse.group = cs;
branchlength += find_minlength(re, cs, startcode, options,
&this_recurse);
&this_recurse, countptr);
}
}
cc += 1 + LINK_SIZE;
@ -1453,6 +1459,7 @@ pcre32_study(const pcre32 *external_re, int options, const char **errorptr)
#endif
{
int min;
int count = 0;
BOOL bits_set = FALSE;
pcre_uint8 start_bits[32];
PUBL(extra) *extra = NULL;
@ -1539,7 +1546,7 @@ if ((re->options & PCRE_ANCHORED) == 0 &&
/* Find the minimum length of subject string. */
switch(min = find_minlength(re, code, code, re->options, NULL))
switch(min = find_minlength(re, code, code, re->options, NULL, &count))
{
case -2: *errorptr = "internal error: missing capturing bracket"; return NULL;
case -3: *errorptr = "internal error: opcode not recognized"; return NULL;

View File

@ -96,6 +96,15 @@
#define SLJIT_EXECUTABLE_ALLOCATOR 1
#endif
/* Force cdecl calling convention even if a better calling
convention (e.g. fastcall) is supported by the C compiler.
If this option is enabled, C functions without
SLJIT_CALL can also be called from JIT code. */
#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION
/* Disabled by default */
#define SLJIT_USE_CDECL_CALLING_CONVENTION 0
#endif
/* Return with error when an invalid argument is passed. */
#ifndef SLJIT_ARGUMENT_CHECKS
/* Disabled by default */

View File

@ -468,7 +468,12 @@ typedef double sljit_d;
#ifndef SLJIT_CALL
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION)
/* Force cdecl. */
#define SLJIT_CALL
#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#if defined(__GNUC__) && !defined(__APPLE__)
@ -608,6 +613,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
#define SLJIT_LOCALS_OFFSET_BASE ((23 + 1) * sizeof(sljit_sw))
#endif
#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
#define SLJIT_NUMBER_OF_REGISTERS 10
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 5
#define SLJIT_LOCALS_OFFSET_BASE 0
#elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
#define SLJIT_NUMBER_OF_REGISTERS 0

View File

@ -845,8 +845,8 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
}
static SLJIT_CONST char* op0_names[] = {
(char*)"breakpoint", (char*)"nop",
(char*)"lumul", (char*)"lsmul", (char*)"ludiv", (char*)"lsdiv",
(char*)"breakpoint", (char*)"nop", (char*)"lumul", (char*)"lsmul",
(char*)"udivmod", (char*)"sdivmod", (char*)"udivi", (char*)"sdivi"
};
static SLJIT_CONST char* op1_names[] = {
@ -1036,7 +1036,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LSMUL)
|| ((op & ~SLJIT_INT_OP) >= SLJIT_LUDIV && (op & ~SLJIT_INT_OP) <= SLJIT_LSDIV));
|| ((op & ~SLJIT_INT_OP) >= SLJIT_UDIVMOD && (op & ~SLJIT_INT_OP) <= SLJIT_SDIVI));
CHECK_ARGUMENT(op < SLJIT_LUMUL || compiler->scratches >= 2);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
@ -1447,6 +1447,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
{
SLJIT_UNUSED_ARG(offset);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
FUNCTION_CHECK_DST(dst, dstw);
#endif
@ -1462,6 +1464,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_co
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
{
SLJIT_UNUSED_ARG(init_value);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
FUNCTION_CHECK_DST(dst, dstw);
#endif

View File

@ -687,7 +687,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
#define SLJIT_OP0_BASE 0
/* Flags: - (never set any flags)
Note: breakpoint instruction is not supported by all architectures (namely ppc)
Note: breakpoint instruction is not supported by all architectures (e.g. ppc)
It falls back to SLJIT_NOP in those cases. */
#define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0)
/* Flags: - (never set any flags)
@ -696,24 +696,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
#define SLJIT_NOP (SLJIT_OP0_BASE + 1)
/* Flags: - (may destroy flags)
Unsigned multiplication of SLJIT_R0 and SLJIT_R1.
Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */
Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
#define SLJIT_LUMUL (SLJIT_OP0_BASE + 2)
/* Flags: - (may destroy flags)
Signed multiplication of SLJIT_R0 and SLJIT_R1.
Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */
Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
#define SLJIT_LSMUL (SLJIT_OP0_BASE + 3)
/* Flags: I - (may destroy flags)
Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1.
Note: if SLJIT_R1 contains 0, the behaviour is undefined. */
#define SLJIT_LUDIV (SLJIT_OP0_BASE + 4)
#define SLJIT_ILUDIV (SLJIT_LUDIV | SLJIT_INT_OP)
The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
Note: if SLJIT_R1 is 0, the behaviour is undefined. */
#define SLJIT_UDIVMOD (SLJIT_OP0_BASE + 4)
#define SLJIT_IUDIVMOD (SLJIT_UDIVMOD | SLJIT_INT_OP)
/* Flags: I - (may destroy flags)
Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1.
Note: if SLJIT_R1 contains 0, the behaviour is undefined. */
#define SLJIT_LSDIV (SLJIT_OP0_BASE + 5)
#define SLJIT_ILSDIV (SLJIT_LSDIV | SLJIT_INT_OP)
The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
Note: if SLJIT_R1 is 0, the behaviour is undefined.
Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),
the behaviour is undefined. */
#define SLJIT_SDIVMOD (SLJIT_OP0_BASE + 5)
#define SLJIT_ISDIVMOD (SLJIT_SDIVMOD | SLJIT_INT_OP)
/* Flags: I - (may destroy flags)
Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
Note: if SLJIT_R1 is 0, the behaviour is undefined.
Note: SLJIT_SDIV is single precision divide. */
#define SLJIT_UDIVI (SLJIT_OP0_BASE + 6)
#define SLJIT_IUDIVI (SLJIT_UDIVI | SLJIT_INT_OP)
/* Flags: I - (may destroy flags)
Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
Note: if SLJIT_R1 is 0, the behaviour is undefined.
Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),
the behaviour is undefined.
Note: SLJIT_SDIV is single precision divide. */
#define SLJIT_SDIVI (SLJIT_OP0_BASE + 7)
#define SLJIT_ISDIVI (SLJIT_SDIVI | SLJIT_INT_OP)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op);

View File

@ -1833,18 +1833,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
| (reg_map[SLJIT_R0] << 8)
| reg_map[TMP_REG1]);
#endif
case SLJIT_LUDIV:
case SLJIT_LSDIV:
if (compiler->scratches >= 3)
case SLJIT_UDIVMOD:
case SLJIT_SDIVMOD:
case SLJIT_UDIVI:
case SLJIT_SDIVI:
SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2, bad_register_mapping);
if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) {
FAIL_IF(push_inst(compiler, 0xe52d2008 /* str r2, [sp, #-8]! */));
FAIL_IF(push_inst(compiler, 0xe58d1004 /* str r1, [sp, #4] */));
}
else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3))
FAIL_IF(push_inst(compiler, 0xe52d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* str r1/r2, [sp, #-8]! */));
#if defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
(op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
#else
#error "Software divmod functions are needed"
#endif
if (compiler->scratches >= 3)
return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */);
if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) {
FAIL_IF(push_inst(compiler, 0xe59d1004 /* ldr r1, [sp, #4] */));
FAIL_IF(push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */));
}
else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3))
return push_inst(compiler, 0xe49d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* ldr r1/r2, [sp], #8 */);
return SLJIT_SUCCESS;
}

View File

@ -1087,14 +1087,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
saved_regs_size += sizeof(sljit_sw);
}
local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET;
FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
if (saved_regs_size > 0)
FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
}
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
prev = -1;
for (i = SLJIT_S0; i >= tmp; i--) {
if (prev == -1) {
prev = i;
if (!(offs & (1 << 15))) {
prev = i;
continue;
}
FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
offs += 1 << 15;
continue;
}
FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@ -1104,7 +1110,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
if (prev == -1) {
prev = i;
if (!(offs & (1 << 15))) {
prev = i;
continue;
}
FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
offs += 1 << 15;
continue;
}
FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@ -1112,8 +1123,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
prev = -1;
}
if (prev != -1)
FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(TMP_SP) | (offs >> 5)));
SLJIT_ASSERT(prev == -1);
if (compiler->local_size > (63 * sizeof(sljit_sw))) {
/* The local_size is already adjusted by the saved registers. */
@ -1188,7 +1198,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
prev = -1;
for (i = SLJIT_S0; i >= tmp; i--) {
if (prev == -1) {
prev = i;
if (!(offs & (1 << 15))) {
prev = i;
continue;
}
FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
offs += 1 << 15;
continue;
}
FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@ -1198,7 +1213,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
if (prev == -1) {
prev = i;
if (!(offs & (1 << 15))) {
prev = i;
continue;
}
FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
offs += 1 << 15;
continue;
}
FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@ -1206,13 +1226,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
prev = -1;
}
if (prev != -1)
FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(TMP_SP) | (offs >> 5)));
SLJIT_ASSERT(prev == -1);
if (compiler->local_size <= (63 * sizeof(sljit_sw))) {
FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR)
| RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15)));
} else {
} else if (saved_regs_size > 0) {
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
}
@ -1242,12 +1261,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));
FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));
return push_inst(compiler, (op == SLJIT_LUMUL ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
case SLJIT_LUDIV:
case SLJIT_LSDIV:
case SLJIT_UDIVMOD:
case SLJIT_SDIVMOD:
FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));
FAIL_IF(push_inst(compiler, ((op == SLJIT_LUDIV ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)));
FAIL_IF(push_inst(compiler, ((op == SLJIT_UDIVMOD ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)));
FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));
return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
case SLJIT_UDIVI:
case SLJIT_SDIVI:
return push_inst(compiler, ((op == SLJIT_UDIVI ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1));
}
return SLJIT_SUCCESS;

View File

@ -1239,6 +1239,9 @@ extern int __aeabi_idivmod(int numerator, int denominator);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
sljit_sw saved_reg_list[3];
sljit_sw saved_reg_count;
CHECK_ERROR();
CHECK(check_sljit_emit_op0(compiler, op));
@ -1255,24 +1258,53 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
| (reg_map[SLJIT_R0] << 12)
| (reg_map[SLJIT_R0] << 16)
| reg_map[SLJIT_R1]);
case SLJIT_LUDIV:
case SLJIT_LSDIV:
if (compiler->scratches >= 4) {
FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */));
FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */));
} else if (compiler->scratches >= 3)
FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */));
case SLJIT_UDIVMOD:
case SLJIT_SDIVMOD:
case SLJIT_UDIVI:
case SLJIT_SDIVI:
SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12, bad_register_mapping);
saved_reg_count = 0;
if (compiler->scratches >= 4)
saved_reg_list[saved_reg_count++] = 12;
if (compiler->scratches >= 3)
saved_reg_list[saved_reg_count++] = 2;
if (op >= SLJIT_UDIVI)
saved_reg_list[saved_reg_count++] = 1;
if (saved_reg_count > 0) {
FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8)
| (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
if (saved_reg_count >= 2) {
SLJIT_ASSERT(saved_reg_list[1] < 8);
FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */));
}
if (saved_reg_count >= 3) {
SLJIT_ASSERT(saved_reg_list[2] < 8);
FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */));
}
}
#if defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
(op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
#else
#error "Software divmod functions are needed"
#endif
if (compiler->scratches >= 4) {
FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */));
return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */);
} else if (compiler->scratches >= 3)
return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */);
if (saved_reg_count > 0) {
if (saved_reg_count >= 3) {
SLJIT_ASSERT(saved_reg_list[2] < 8);
FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */));
}
if (saved_reg_count >= 2) {
SLJIT_ASSERT(saved_reg_list[1] < 8);
FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */));
}
return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8)
| (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
}
return SLJIT_SUCCESS;
}

View File

@ -1053,8 +1053,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
#endif
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
case SLJIT_LUDIV:
case SLJIT_LSDIV:
case SLJIT_UDIVMOD:
case SLJIT_SDIVMOD:
case SLJIT_UDIVI:
case SLJIT_SDIVI:
SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
#if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
@ -1062,15 +1065,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
if (int_op)
FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
else
FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
#else
FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
#endif
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
return (op >= SLJIT_UDIVI) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
}
return SLJIT_SUCCESS;

View File

@ -1267,22 +1267,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
return push_inst(compiler, (op == SLJIT_LUMUL ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
#endif
case SLJIT_LUDIV:
case SLJIT_LSDIV:
case SLJIT_UDIVMOD:
case SLJIT_SDIVMOD:
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
if (int_op) {
FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
} else {
FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVDU : DIVD) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
}
return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_UDIVMOD ? DIVWU : DIVW) : (op == SLJIT_UDIVMOD ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
#else
FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIVMOD ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
#endif
return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
case SLJIT_UDIVI:
case SLJIT_SDIVI:
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
return push_inst(compiler, (int_op ? (op == SLJIT_UDIVI ? DIVWU : DIVW) : (op == SLJIT_UDIVI ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
#else
return push_inst(compiler, (op == SLJIT_UDIVI ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
#endif
}

View File

@ -777,20 +777,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
#else
#error "Implementation required"
#endif
case SLJIT_LUDIV:
case SLJIT_LSDIV:
case SLJIT_UDIVMOD:
case SLJIT_SDIVMOD:
case SLJIT_UDIVI:
case SLJIT_SDIVI:
SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
if (op == SLJIT_LUDIV)
if ((op | 0x2) == SLJIT_UDIVI)
FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS));
else {
FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_R0) | IMM(31), DR(TMP_REG1)));
FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS));
}
FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
if (op <= SLJIT_SDIVMOD)
FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
if (op >= SLJIT_UDIVI)
return SLJIT_SUCCESS;
FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1)));
FAIL_IF(push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1)));
return SLJIT_SUCCESS;
return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1));
#else
#error "Implementation required"
#endif

View File

@ -35,21 +35,21 @@
#define SIMM_16BIT_MIN (-0x8000)
#define SIMM_17BIT_MAX (0xffff)
#define SIMM_17BIT_MIN (-0x10000)
#define SIMM_32BIT_MIN (-0x80000000)
#define SIMM_32BIT_MAX (0x7fffffff)
#define SIMM_48BIT_MIN (0x800000000000L)
#define SIMM_32BIT_MIN (-0x7fffffff - 1)
#define SIMM_48BIT_MAX (0x7fffffff0000L)
#define SIMM_48BIT_MIN (-0x800000000000L)
#define IMM16(imm) ((imm) & 0xffff)
#define UIMM_16BIT_MAX (0xffff)
#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
#define ADDR_TMP (SLJIT_NO_REGISTERS + 4)
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
#define ADDR_TMP (SLJIT_NUMBER_OF_REGISTERS + 5)
#define PIC_ADDR_REG TMP_REG2
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7
};
@ -58,11 +58,6 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
#define TMP_REG2_mapped 16
#define TMP_REG3_mapped 6
#define ADDR_TMP_mapped 7
#define SLJIT_SAVED_REG1_mapped 30
#define SLJIT_SAVED_REG2_mapped 31
#define SLJIT_SAVED_REG3_mapped 32
#define SLJIT_SAVED_EREG1_mapped 33
#define SLJIT_SAVED_EREG2_mapped 34
/* Flags are keept in volatile registers. */
#define EQUAL_FLAG 8
@ -399,6 +394,9 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
#define SUB(dst, srca, srcb) \
push_3_buffer(compiler, TILEGX_OPC_SUB, dst, srca, srcb, __LINE__)
#define MUL(dst, srca, srcb) \
push_3_buffer(compiler, TILEGX_OPC_MULX, dst, srca, srcb, __LINE__)
#define NOR(dst, srca, srcb) \
push_3_buffer(compiler, TILEGX_OPC_NOR, dst, srca, srcb, __LINE__)
@ -547,8 +545,8 @@ const struct Format* compute_format()
const struct Format* match = NULL;
const struct Format *b = NULL;
unsigned int i = 0;
for (i; i < sizeof formats / sizeof formats[0]; i++) {
unsigned int i;
for (i = 0; i < sizeof formats / sizeof formats[0]; i++) {
b = &formats[i];
if ((b->pipe_mask & compatible_pipes) == b->pipe_mask) {
match = b;
@ -625,7 +623,6 @@ tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst)
static sljit_si update_buffer(struct sljit_compiler *compiler)
{
int count;
int i;
int orig_index = inst_buf_index;
struct jit_instr inst0 = inst_buf[0];
@ -738,8 +735,10 @@ static sljit_si update_buffer(struct sljit_compiler *compiler)
static sljit_si flush_buffer(struct sljit_compiler *compiler)
{
while (inst_buf_index != 0)
update_buffer(compiler);
while (inst_buf_index != 0) {
FAIL_IF(update_buffer(compiler));
}
return SLJIT_SUCCESS;
}
static sljit_si push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line)
@ -787,6 +786,7 @@ static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
case TILEGX_OPC_ADD:
case TILEGX_OPC_AND:
case TILEGX_OPC_SUB:
case TILEGX_OPC_MULX:
case TILEGX_OPC_OR:
case TILEGX_OPC_XOR:
case TILEGX_OPC_NOR:
@ -905,7 +905,6 @@ static SLJIT_INLINE sljit_ins * detect_jump_type(struct sljit_jump *jump, sljit_
sljit_sw diff;
sljit_uw target_addr;
sljit_ins *inst;
sljit_ins saved_inst;
if (jump->flags & SLJIT_REWRITABLE_JUMP)
return code_ptr;
@ -1009,7 +1008,7 @@ SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compi
struct sljit_const *const_;
CHECK_ERROR_PTR();
check_sljit_generate_code(compiler);
CHECK_PTR(check_sljit_generate_code(compiler));
reverse_buf(compiler);
code = (sljit_ins *)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
@ -1178,13 +1177,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
{
sljit_ins base;
sljit_ins bundle = 0;
sljit_si i, tmp;
CHECK_ERROR();
check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
local_size += (saveds + 1) * sizeof(sljit_sw);
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
local_size = (local_size + 7) & ~7;
compiler->local_size = local_size;
@ -1200,56 +1199,52 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
local_size = 0;
}
/* Save the return address. */
FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8));
FAIL_IF(ST_ADD(ADDR_TMP_mapped, RA, -8));
if (saveds >= 1)
FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG1_mapped, -8));
/* Save the S registers. */
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
for (i = SLJIT_S0; i >= tmp; i--) {
FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8));
}
if (saveds >= 2)
FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG2_mapped, -8));
/* Save the R registers that need to be reserved. */
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8));
}
if (saveds >= 3)
FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG3_mapped, -8));
if (saveds >= 4)
FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG1_mapped, -8));
if (saveds >= 5)
FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG2_mapped, -8));
if (args >= 1)
FAIL_IF(ADD(SLJIT_SAVED_REG1_mapped, 0, ZERO));
if (args >= 2)
FAIL_IF(ADD(SLJIT_SAVED_REG2_mapped, 1, ZERO));
if (args >= 3)
FAIL_IF(ADD(SLJIT_SAVED_REG3_mapped, 2, ZERO));
/* Move the arguments to S registers. */
for (i = 0; i < args; i++) {
FAIL_IF(ADD(reg_map[SLJIT_S0 - i], i, ZERO));
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
{
CHECK_ERROR_VOID();
check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
CHECK_ERROR();
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
local_size += (saveds + 1) * sizeof(sljit_sw);
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
compiler->local_size = (local_size + 7) & ~7;
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
sljit_si local_size;
sljit_ins base;
int addr_initialized = 0;
sljit_si i, tmp;
sljit_si saveds;
CHECK_ERROR();
check_sljit_emit_return(compiler, op, src, srcw);
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
@ -1263,50 +1258,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
local_size = 0;
}
/* Restore the return address. */
FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8));
FAIL_IF(LD(RA, ADDR_TMP_mapped));
FAIL_IF(LD_ADD(RA, ADDR_TMP_mapped, -8));
if (compiler->saveds >= 5) {
FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 48));
addr_initialized = 1;
FAIL_IF(LD_ADD(SLJIT_SAVED_EREG2_mapped, ADDR_TMP_mapped, 8));
/* Restore the S registers. */
saveds = compiler->saveds;
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
for (i = SLJIT_S0; i >= tmp; i--) {
FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8));
}
if (compiler->saveds >= 4) {
if (addr_initialized == 0) {
FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 40));
addr_initialized = 1;
}
FAIL_IF(LD_ADD(SLJIT_SAVED_EREG1_mapped, ADDR_TMP_mapped, 8));
}
if (compiler->saveds >= 3) {
if (addr_initialized == 0) {
FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 32));
addr_initialized = 1;
}
FAIL_IF(LD_ADD(SLJIT_SAVED_REG3_mapped, ADDR_TMP_mapped, 8));
}
if (compiler->saveds >= 2) {
if (addr_initialized == 0) {
FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 24));
addr_initialized = 1;
}
FAIL_IF(LD_ADD(SLJIT_SAVED_REG2_mapped, ADDR_TMP_mapped, 8));
}
if (compiler->saveds >= 1) {
if (addr_initialized == 0) {
FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 16));
/* addr_initialized = 1; no need to initialize as it's the last one. */
}
FAIL_IF(LD_ADD(SLJIT_SAVED_REG1_mapped, ADDR_TMP_mapped, 8));
/* Restore the R registers that need to be reserved. */
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8));
}
if (compiler->local_size <= SIMM_16BIT_MAX)
@ -1585,7 +1550,7 @@ static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
CHECK_ERROR();
check_sljit_emit_fast_enter(compiler, dst, dstw);
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
/* For UNUSED dst. Uncommon, but possible. */
@ -1602,7 +1567,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
check_sljit_emit_fast_return(compiler, src, srcw);
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
if (FAST_IS_REG(src))
@ -1636,9 +1601,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
if (op == SLJIT_MOV_SI)
return BFEXTS(reg_map[dst], reg_map[src2], 0, 31);
return BFEXTU(reg_map[dst], reg_map[src2], 0, 31);
} else if (dst != src2)
SLJIT_ASSERT_STOP();
return BFEXTU(reg_map[dst], reg_map[src2], 0, 31);
} else if (dst != src2) {
SLJIT_ASSERT(src2 == 0);
return ADD(reg_map[dst], reg_map[src2], ZERO);
}
return SLJIT_SUCCESS;
@ -1650,8 +1617,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
return BFEXTS(reg_map[dst], reg_map[src2], 0, 7);
return BFEXTU(reg_map[dst], reg_map[src2], 0, 7);
} else if (dst != src2)
SLJIT_ASSERT_STOP();
} else if (dst != src2) {
SLJIT_ASSERT(src2 == 0);
return ADD(reg_map[dst], reg_map[src2], ZERO);
}
return SLJIT_SUCCESS;
@ -1663,8 +1632,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
return BFEXTS(reg_map[dst], reg_map[src2], 0, 15);
return BFEXTU(reg_map[dst], reg_map[src2], 0, 15);
} else if (dst != src2)
SLJIT_ASSERT_STOP();
} else if (dst != src2) {
SLJIT_ASSERT(src2 == 0);
return ADD(reg_map[dst], reg_map[src2], ZERO);
}
return SLJIT_SUCCESS;
@ -1811,7 +1782,6 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
else {
/* Rare ocasion. */
FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));
overflow_ra = TMP_EREG2;
}
}
@ -1903,6 +1873,17 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
return SLJIT_SUCCESS;
case SLJIT_MUL:
if (flags & SRC2_IMM) {
FAIL_IF(load_immediate(compiler, TMP_REG2_mapped, src2));
src2 = TMP_REG2;
flags &= ~SRC2_IMM;
}
FAIL_IF(MUL(reg_map[dst], reg_map[src1], reg_map[src2]));
return SLJIT_SUCCESS;
#define EMIT_LOGICAL(op_imm, op_norm) \
if (flags & SRC2_IMM) { \
FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); \
@ -1950,8 +1931,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
} else { \
if (op & SLJIT_SET_E) \
FAIL_IF(push_3_buffer( \
compiler, op_imm, reg_map[dst], reg_map[src1], \
src2 & 0x3F, __LINE__)); \
compiler, op_norm, EQUAL_FLAG, reg_map[src1], \
reg_map[src2], __LINE__)); \
if (CHECK_FLAGS(SLJIT_SET_E)) \
FAIL_IF(push_3_buffer( \
compiler, op_norm, reg_map[dst], reg_map[src1], \
@ -2105,66 +2086,61 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
{
sljit_si sugg_dst_ar, dst_ar;
sljit_si flags = GET_ALL_FLAGS(op);
sljit_si mem_type = (op & SLJIT_INT_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
CHECK_ERROR();
check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
op = GET_OPCODE(op);
if (op == SLJIT_MOV_SI || op == SLJIT_MOV_UI)
mem_type = INT_DATA | SIGNED_DATA;
sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2];
compiler->cache_arg = 0;
compiler->cache_argw = 0;
if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
ADJUST_LOCAL_OFFSET(src, srcw);
FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw));
FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw));
src = TMP_REG1;
srcw = 0;
}
switch (type) {
case SLJIT_C_EQUAL:
case SLJIT_C_NOT_EQUAL:
switch (type & 0xff) {
case SLJIT_EQUAL:
case SLJIT_NOT_EQUAL:
FAIL_IF(CMPLTUI(sugg_dst_ar, EQUAL_FLAG, 1));
dst_ar = sugg_dst_ar;
break;
case SLJIT_C_LESS:
case SLJIT_C_GREATER_EQUAL:
case SLJIT_C_FLOAT_LESS:
case SLJIT_C_FLOAT_GREATER_EQUAL:
case SLJIT_LESS:
case SLJIT_GREATER_EQUAL:
dst_ar = ULESS_FLAG;
break;
case SLJIT_C_GREATER:
case SLJIT_C_LESS_EQUAL:
case SLJIT_C_FLOAT_GREATER:
case SLJIT_C_FLOAT_LESS_EQUAL:
case SLJIT_GREATER:
case SLJIT_LESS_EQUAL:
dst_ar = UGREATER_FLAG;
break;
case SLJIT_C_SIG_LESS:
case SLJIT_C_SIG_GREATER_EQUAL:
case SLJIT_SIG_LESS:
case SLJIT_SIG_GREATER_EQUAL:
dst_ar = LESS_FLAG;
break;
case SLJIT_C_SIG_GREATER:
case SLJIT_C_SIG_LESS_EQUAL:
case SLJIT_SIG_GREATER:
case SLJIT_SIG_LESS_EQUAL:
dst_ar = GREATER_FLAG;
break;
case SLJIT_C_OVERFLOW:
case SLJIT_C_NOT_OVERFLOW:
case SLJIT_OVERFLOW:
case SLJIT_NOT_OVERFLOW:
dst_ar = OVERFLOW_FLAG;
break;
case SLJIT_C_MUL_OVERFLOW:
case SLJIT_C_MUL_NOT_OVERFLOW:
case SLJIT_MUL_OVERFLOW:
case SLJIT_MUL_NOT_OVERFLOW:
FAIL_IF(CMPLTUI(sugg_dst_ar, OVERFLOW_FLAG, 1));
dst_ar = sugg_dst_ar;
type ^= 0x1; /* Flip type bit for the XORI below. */
break;
case SLJIT_C_FLOAT_EQUAL:
case SLJIT_C_FLOAT_NOT_EQUAL:
dst_ar = EQUAL_FLAG;
break;
default:
SLJIT_ASSERT_STOP();
@ -2180,11 +2156,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
if (op >= SLJIT_ADD) {
if (TMP_REG2_mapped != dst_ar)
FAIL_IF(ADD(TMP_REG2_mapped, dst_ar, ZERO));
return emit_op(compiler, op | flags, CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
}
if (dst & SLJIT_MEM)
return emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw);
return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw);
if (sugg_dst_ar != dst_ar)
return ADD(sugg_dst_ar, dst_ar, ZERO);
@ -2194,7 +2170,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) {
CHECK_ERROR();
check_sljit_emit_op0(compiler, op);
CHECK(check_sljit_emit_op0(compiler, op));
op = GET_OPCODE(op);
switch (op) {
@ -2204,10 +2180,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
case SLJIT_BREAKPOINT:
return PI(BPT);
case SLJIT_UMUL:
case SLJIT_SMUL:
case SLJIT_UDIV:
case SLJIT_SDIV:
case SLJIT_LUMUL:
case SLJIT_LSMUL:
case SLJIT_UDIVI:
case SLJIT_SDIVI:
SLJIT_ASSERT_STOP();
}
@ -2217,7 +2193,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
@ -2273,7 +2249,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
case SLJIT_CLZ:
return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
return emit_op(compiler, op, (op & SLJIT_INT_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
}
return SLJIT_SUCCESS;
@ -2282,7 +2258,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w)
{
CHECK_ERROR();
check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
@ -2325,7 +2301,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_comp
flush_buffer(compiler);
CHECK_ERROR_PTR();
check_sljit_emit_label(compiler);
CHECK_PTR(check_sljit_emit_label(compiler));
if (compiler->last_label && compiler->last_label->size == compiler->size)
return compiler->last_label;
@ -2344,7 +2320,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
flush_buffer(compiler);
CHECK_ERROR();
check_sljit_emit_ijump(compiler, type, src, srcw);
CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
if (FAST_IS_REG(src)) {
@ -2404,8 +2380,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
return SLJIT_SUCCESS;
} else if (src & SLJIT_MEM)
} else if (src & SLJIT_MEM) {
FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
flush_buffer(compiler);
}
FAIL_IF(JR_SOLO(reg_map[src_r]));
@ -2432,7 +2410,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil
flush_buffer(compiler);
CHECK_ERROR_PTR();
check_sljit_emit_jump(compiler, type);
CHECK_PTR(check_sljit_emit_jump(compiler, type));
jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
@ -2440,48 +2418,42 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil
type &= 0xff;
switch (type) {
case SLJIT_C_EQUAL:
case SLJIT_C_FLOAT_NOT_EQUAL:
case SLJIT_EQUAL:
BR_NZ(EQUAL_FLAG);
break;
case SLJIT_C_NOT_EQUAL:
case SLJIT_C_FLOAT_EQUAL:
case SLJIT_NOT_EQUAL:
BR_Z(EQUAL_FLAG);
break;
case SLJIT_C_LESS:
case SLJIT_C_FLOAT_LESS:
case SLJIT_LESS:
BR_Z(ULESS_FLAG);
break;
case SLJIT_C_GREATER_EQUAL:
case SLJIT_C_FLOAT_GREATER_EQUAL:
case SLJIT_GREATER_EQUAL:
BR_NZ(ULESS_FLAG);
break;
case SLJIT_C_GREATER:
case SLJIT_C_FLOAT_GREATER:
case SLJIT_GREATER:
BR_Z(UGREATER_FLAG);
break;
case SLJIT_C_LESS_EQUAL:
case SLJIT_C_FLOAT_LESS_EQUAL:
case SLJIT_LESS_EQUAL:
BR_NZ(UGREATER_FLAG);
break;
case SLJIT_C_SIG_LESS:
case SLJIT_SIG_LESS:
BR_Z(LESS_FLAG);
break;
case SLJIT_C_SIG_GREATER_EQUAL:
case SLJIT_SIG_GREATER_EQUAL:
BR_NZ(LESS_FLAG);
break;
case SLJIT_C_SIG_GREATER:
case SLJIT_SIG_GREATER:
BR_Z(GREATER_FLAG);
break;
case SLJIT_C_SIG_LESS_EQUAL:
case SLJIT_SIG_LESS_EQUAL:
BR_NZ(GREATER_FLAG);
break;
case SLJIT_C_OVERFLOW:
case SLJIT_C_MUL_OVERFLOW:
case SLJIT_OVERFLOW:
case SLJIT_MUL_OVERFLOW:
BR_Z(OVERFLOW_FLAG);
break;
case SLJIT_C_NOT_OVERFLOW:
case SLJIT_C_MUL_NOT_OVERFLOW:
case SLJIT_NOT_OVERFLOW:
case SLJIT_MUL_NOT_OVERFLOW:
BR_NZ(OVERFLOW_FLAG);
break;
default:
@ -2536,7 +2508,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_comp
flush_buffer(compiler);
CHECK_ERROR_PTR();
check_sljit_emit_const(compiler, dst, dstw, init_value);
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));
@ -2572,3 +2544,18 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
inst[3] = (inst[3] & ~(0xFFFFL << 43)) | ((new_constant & 0xFFFFL) << 43);
SLJIT_CACHE_FLUSH(inst, inst + 4);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
{
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
return reg_map[reg];
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
void *instruction, sljit_si size)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
return SLJIT_ERR_UNSUPPORTED;
}

View File

@ -744,8 +744,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
break;
case SLJIT_LUMUL:
case SLJIT_LSMUL:
case SLJIT_LUDIV:
case SLJIT_LSDIV:
case SLJIT_UDIVMOD:
case SLJIT_SDIVMOD:
case SLJIT_UDIVI:
case SLJIT_SDIVI:
compiler->flags_saved = 0;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
#ifdef _WIN64
@ -763,9 +765,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
#endif
compiler->mode32 = op & SLJIT_INT_OP;
#endif
SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
op = GET_OPCODE(op);
if (op == SLJIT_LUDIV) {
if ((op | 0x2) == SLJIT_UDIVI) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0);
@ -776,7 +779,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
*inst = XOR_r_rm;
}
if (op == SLJIT_LSDIV) {
if ((op | 0x2) == SLJIT_SDIVI) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
#endif
@ -807,10 +810,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
FAIL_IF(!inst);
INC_SIZE(2);
*inst++ = GROUP_F7;
*inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);
*inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);
#else
#ifdef _WIN64
size = (!compiler->mode32 || op >= SLJIT_LUDIV) ? 3 : 2;
size = (!compiler->mode32 || op >= SLJIT_UDIVMOD) ? 3 : 2;
#else
size = (!compiler->mode32) ? 3 : 2;
#endif
@ -819,11 +822,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
INC_SIZE(size);
#ifdef _WIN64
if (!compiler->mode32)
*inst++ = REX_W | ((op >= SLJIT_LUDIV) ? REX_B : 0);
else if (op >= SLJIT_LUDIV)
*inst++ = REX_W | ((op >= SLJIT_UDIVMOD) ? REX_B : 0);
else if (op >= SLJIT_UDIVMOD)
*inst++ = REX_B;
*inst++ = GROUP_F7;
*inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);
*inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);
#else
if (!compiler->mode32)
*inst++ = REX_W;
@ -838,15 +841,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
case SLJIT_LSMUL:
*inst |= IMUL;
break;
case SLJIT_LUDIV:
case SLJIT_UDIVMOD:
case SLJIT_UDIVI:
*inst |= DIV;
break;
case SLJIT_LSDIV:
case SLJIT_SDIVMOD:
case SLJIT_SDIVI:
*inst |= IDIV;
break;
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
if (op <= SLJIT_SDIVMOD)
EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
#else
if (op >= SLJIT_UDIVI)
EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
#endif
break;
}
@ -1907,60 +1916,62 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
if (FAST_IS_REG(src1)) {
if (!(src1 & SLJIT_IMM)) {
if (src2 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (IS_HALFWORD(src2w) || compiler->mode32) {
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);
FAIL_IF(!inst);
*inst = GROUP_F7;
}
else {
FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0);
inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, src1w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
}
#else
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);
FAIL_IF(!inst);
*inst = GROUP_F7;
#endif
return SLJIT_SUCCESS;
}
else {
else if (FAST_IS_REG(src1)) {
inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
return SLJIT_SUCCESS;
}
return SLJIT_SUCCESS;
}
if (FAST_IS_REG(src2)) {
if (!(src2 & SLJIT_IMM)) {
if (src1 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (IS_HALFWORD(src1w) || compiler->mode32) {
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0);
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w);
FAIL_IF(!inst);
*inst = GROUP_F7;
}
else {
FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0);
inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, src2w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
}
#else
inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0);
inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w);
FAIL_IF(!inst);
*inst = GROUP_F7;
#endif
return SLJIT_SUCCESS;
}
else {
else if (FAST_IS_REG(src2)) {
inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
return SLJIT_SUCCESS;
}
return SLJIT_SUCCESS;
}
EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);

View File

@ -40,15 +40,15 @@ SOURCES += \
$$ANGLE_DIR/src/compiler/preprocessor/Preprocessor.cpp \
$$ANGLE_DIR/src/compiler/preprocessor/Token.cpp
# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin
flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
# NOTE: 'flex' and 'bison' can be found in qt5/gnuwin32/bin
flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
flex.output = ${QMAKE_FILE_BASE}.cpp
flex.input = FLEX_SOURCES
flex.dependency_type = TYPE_C
flex.variable_out = GENERATED_SOURCES
QMAKE_EXTRA_COMPILERS += flex
bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
bison.output = ${QMAKE_FILE_BASE}.cpp
bison.input = BISON_SOURCES
bison.dependency_type = TYPE_C

View File

@ -162,15 +162,15 @@ SOURCES += \
$$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.cpp
# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin
flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME}
# NOTE: 'flex' and 'bison' can be found in qt5/gnuwin32/bin
flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME}
flex.output = ${QMAKE_FILE_BASE}_lex.cpp
flex.input = FLEX_SOURCES
flex.dependency_type = TYPE_C
flex.variable_out = GENERATED_SOURCES
QMAKE_EXTRA_COMPILERS += flex
bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \
bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \
--output=${QMAKE_FILE_BASE}_tab.cpp ${QMAKE_FILE_NAME}
bison.output = ${QMAKE_FILE_BASE}_tab.h
bison.input = BISON_SOURCES

View File

@ -2658,6 +2658,7 @@
\value ItemIsTristate \e{This enum value is deprecated.} Use Qt::ItemIsAutoTristate
instead.
\value ItemNeverHasChildren The item never has child items.
This is used for optimization purposes only.
\value ItemIsUserTristate The user can cycle through three separate states.
This value has been added in Qt 5.5.

View File

@ -263,6 +263,7 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
groupId(). You can examine a file's permissions and ownership in a
single statement using the permission() function.
\target NTFS permissions
\note On NTFS file systems, ownership and permissions checking is
disabled by default for performance reasons. To enable it,
include the following line:
@ -893,6 +894,9 @@ QDir QFileInfo::absoluteDir() const
/*!
Returns \c true if the user can read the file; otherwise returns \c false.
\note If the \l{NTFS permissions} check has not been enabled, the result
on Windows will merely reflect whether the file exists.
\sa isWritable(), isExecutable(), permission()
*/
bool QFileInfo::isReadable() const
@ -911,6 +915,9 @@ bool QFileInfo::isReadable() const
/*!
Returns \c true if the user can write to the file; otherwise returns \c false.
\note If the \l{NTFS permissions} check has not been enabled, the result on
Windows will merely reflect whether the file is marked as Read Only.
\sa isReadable(), isExecutable(), permission()
*/
bool QFileInfo::isWritable() const
@ -1137,7 +1144,8 @@ QString QFileInfo::readLink() const
returned.
This function can be time consuming under Unix (in the order of
milliseconds).
milliseconds). On Windows, it will return an empty string unless
the \l{NTFS permissions} check has been enabled.
\sa ownerId(), group(), groupId()
*/
@ -1217,6 +1225,9 @@ uint QFileInfo::groupId() const
On systems where files do not have permissions this function
always returns \c true.
\note The result might be inaccurate on Windows if the
\l{NTFS permissions} check has not been enabled.
Example:
\snippet code/src_corelib_io_qfileinfo.cpp 10
@ -1240,6 +1251,9 @@ bool QFileInfo::permission(QFile::Permissions permissions) const
/*!
Returns the complete OR-ed together combination of
QFile::Permissions for the file.
\note The result might be inaccurate on Windows if the
\l{NTFS permissions} check has not been enabled.
*/
QFile::Permissions QFileInfo::permissions() const
{

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2014 Intel Corporation
** Copyright (C) 2015 Intel Corporation
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@ -139,7 +139,7 @@ QT_BEGIN_NAMESPACE
Unix environment allows both variable names and contents to contain arbitrary
binary data (except for the NUL character). QProcessEnvironment will preserve
such variables, but does not support manipulating variables whose names or
values are not encodable by the current locale settings (see
values cannot be encoded by the current locale settings (see
QTextCodec::codecForLocale).
On Windows, the variable names are case-insensitive, but case-preserving.
@ -395,8 +395,8 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa
Use with the QProcess::setEnvironment function is not recommended due to
potential encoding problems under Unix, and worse performance.
\sa systemEnvironment(), QProcess::systemEnvironment(), QProcess::environment(),
QProcess::setEnvironment()
\sa systemEnvironment(), QProcess::systemEnvironment(),
QProcess::setProcessEnvironment()
*/
QStringList QProcessEnvironment::toStringList() const
{
@ -545,7 +545,7 @@ void QProcessPrivate::Channel::clear()
QProcess can merge the two output channels, so that standard
output and standard error data from the running process both use
the standard output channel. Call setProcessChannelMode() with
MergedChannels before starting the process to activative
MergedChannels before starting the process to activate
this feature. You also have the option of forwarding the output of
the running process to the calling, main process, by passing
ForwardedChannels as the argument. It is also possible to forward
@ -556,7 +556,7 @@ void QProcessPrivate::Channel::clear()
Certain processes need special environment settings in order to
operate. You can set environment variables for your process by
calling setEnvironment(). To set a working directory, call
calling setProcessEnvironment(). To set a working directory, call
setWorkingDirectory(). By default, processes are run in the
current working directory of the calling process.
@ -1328,7 +1328,7 @@ QProcess::InputChannelMode QProcess::inputChannelMode() const
/*!
\since 5.2
Sets the channel mode of the QProcess standard intput
Sets the channel mode of the QProcess standard input
channel to the \a mode specified.
This mode will be used the next time start() is called.
@ -2195,6 +2195,7 @@ void QProcessPrivate::start(QIODevice::OpenMode mode)
qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')';
#endif
stdinChannel.buffer.clear();
stdoutChannel.buffer.clear();
stderrChannel.buffer.clear();
@ -2393,7 +2394,7 @@ void QProcess::setArguments(const QStringList &arguments)
The process may not exit as a result of calling this function (it is given
the chance to prompt the user for any unsaved files, etc).
On Windows, terminate() posts a WM_CLOSE message to all toplevel windows
On Windows, terminate() posts a WM_CLOSE message to all top-level windows
of the process and then to the main thread of the process itself. On Unix
and OS X the \c SIGTERM signal is sent.
@ -2589,14 +2590,14 @@ QT_END_INCLUDE_NAMESPACE
This function does not cache the system environment. Therefore, it's
possible to obtain an updated version of the environment if low-level C
library functions like \tt setenv ot \tt putenv have been called.
library functions like \tt setenv or \tt putenv have been called.
However, note that repeated calls to this function will recreate the
list of environment variables, which is a non-trivial operation.
\note For new code, it is recommended to use QProcessEnvironment::systemEnvironment()
\sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment()
\sa QProcessEnvironment::systemEnvironment(), setProcessEnvironment()
*/
QStringList QProcess::systemEnvironment()
{
@ -2619,7 +2620,7 @@ QStringList QProcess::systemEnvironment()
It is returned as a QProcessEnvironment. This function does not
cache the system environment. Therefore, it's possible to obtain
an updated version of the environment if low-level C library
functions like \tt setenv ot \tt putenv have been called.
functions like \tt setenv or \tt putenv have been called.
However, note that repeated calls to this function will recreate the
QProcessEnvironment object, which is a non-trivial operation.

View File

@ -694,13 +694,15 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
return true;
// If we wouldn't write anything, check if we can read stdout.
if (bytesAvailableInChannel(&stdoutChannel) != 0) {
if (stdoutChannel.pipe[0] != INVALID_Q_PIPE
&& bytesAvailableInChannel(&stdoutChannel) != 0) {
tryReadFromChannel(&stdoutChannel);
timer.resetIncrements();
}
// Check if we can read stderr.
if (bytesAvailableInChannel(&stderrChannel) != 0) {
if (stderrChannel.pipe[0] != INVALID_Q_PIPE
&& bytesAvailableInChannel(&stderrChannel) != 0) {
tryReadFromChannel(&stderrChannel);
timer.resetIncrements();
}

View File

@ -507,9 +507,9 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
valid = true;
ready = true;
bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize;
bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize;
bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
blockSize = statfs_buf.f_bsize;
#if defined(Q_OS_ANDROID) || defined (Q_OS_BSD4)
#if defined(_STATFS_F_FLAGS)

View File

@ -85,7 +85,7 @@ qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
return -1;
QMutexLocker locker(&lock);
data.append(QByteArray(ptr, maxlen));
data.append(ptr, maxlen);
waitCondition.wakeOne();
return maxlen;
}

View File

@ -1395,6 +1395,8 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
Note that the destroyed() signal will be emitted even if the signals
for this object have been blocked.
Signals emitted while being blocked are not buffered.
\sa signalsBlocked()
*/

View File

@ -79,10 +79,9 @@ Q_CORE_EXPORT int qmime_secondsBetweenChecks = 5; // exported for the unit test
bool QMimeProviderBase::shouldCheck()
{
const QDateTime now = QDateTime::currentDateTime();
if (m_lastCheck.isValid() && m_lastCheck.secsTo(now) < qmime_secondsBetweenChecks)
if (m_lastCheck.isValid() && m_lastCheck.elapsed() < qmime_secondsBetweenChecks * 1000)
return false;
m_lastCheck = now;
m_lastCheck.start();
return true;
}
@ -562,10 +561,13 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
// load comment and globPatterns
const QString file = data.name + QLatin1String(".xml");
const QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file);
// shared-mime-info since 1.3 lowercases the xml files
QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file.toLower());
if (mimeFiles.isEmpty()) {
// TODO: ask Thiago about this
qWarning() << "No file found for" << file << ", even though the file appeared in a directory listing.";
mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file); // pre-1.3
}
if (mimeFiles.isEmpty()) {
qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist.";
qWarning() << "Either it was just removed, or the directory doesn't have executable permission...";
qWarning() << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory);
return;
@ -626,7 +628,7 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
// Let's assume that shared-mime-info is at least version 0.70
// Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file.
#if 1
if (!mainPattern.isEmpty() && data.globPatterns.first() != mainPattern) {
if (!mainPattern.isEmpty() && (data.globPatterns.isEmpty() || data.globPatterns.first() != mainPattern)) {
// ensure it's first in the list of patterns
data.globPatterns.removeAll(mainPattern);
data.globPatterns.prepend(mainPattern);

View File

@ -51,6 +51,7 @@
#include <QtCore/qdatetime.h>
#include <QtCore/qset.h>
#include <QtCore/qelapsedtimer.h>
QT_BEGIN_NAMESPACE
@ -77,7 +78,7 @@ public:
QMimeDatabasePrivate *m_db;
protected:
bool shouldCheck();
QDateTime m_lastCheck;
QElapsedTimer m_lastCheck;
};
/*

View File

@ -563,7 +563,28 @@ const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
};
typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList;
Q_GLOBAL_STATIC(FreeList, freelist);
// We cannot use Q_GLOBAL_STATIC because it uses QMutex
#if defined(Q_COMPILER_THREADSAFE_STATICS)
FreeList *freelist()
{
static FreeList list;
return &list;
}
#else
FreeList *freelist()
{
static QAtomicPointer<FreeList> list;
FreeList *local = list.loadAcquire();
if (!local) {
local = new FreeList;
if (!list.testAndSetRelease(0, local)) {
delete local;
local = list.loadAcquire();
}
}
return local;
}
#endif
}
QMutexPrivate *QMutexPrivate::allocate()

View File

@ -46,21 +46,21 @@ SOURCES += thread/qatomic.cpp \
unix:SOURCES += thread/qthread_unix.cpp \
thread/qwaitcondition_unix.cpp
win32:SOURCES += thread/qmutex_win.cpp \
thread/qthread_win.cpp \
win32:SOURCES += thread/qthread_win.cpp \
thread/qwaitcondition_win.cpp
integrity:SOURCES += thread/qmutex_unix.cpp \
thread/qthread_unix.cpp \
integrity:SOURCES += thread/qthread_unix.cpp \
thread/qwaitcondition_unix.cpp
unix: {
mac {
SOURCES += thread/qmutex_mac.cpp
} else:linux-*:!linux-lsb-* {
SOURCES += thread/qmutex_linux.cpp
} else {
SOURCES += thread/qmutex_unix.cpp
}
false {
# files #included by others, but listed here so IDEs parsing this file know
# they are part of QtCore. Usually, qmake can find out that certain files
# are #included by others and thus remove from SOURCES, but it gets lost
# with qmutex.cpp.
SOURCES += \
thread/qmutex_linux.cpp \
thread/qmutex_mac.cpp \
thread/qmutex_unix.cpp \
thread/qmutex_win.cpp
}

View File

@ -598,12 +598,22 @@ QT_BEGIN_NAMESPACE
\fn QChar::QChar(char ch)
Constructs a QChar corresponding to ASCII/Latin-1 character \a ch.
\note This constructor is not available when \c QT_NO_CAST_FROM_ASCII
is defined.
\sa QT_NO_CAST_FROM_ASCII
*/
/*!
\fn QChar::QChar(uchar ch)
Constructs a QChar corresponding to ASCII/Latin-1 character \a ch.
\note This constructor is not available when \c QT_NO_CAST_FROM_ASCII
is defined.
\sa QT_NO_CAST_FROM_ASCII
*/
/*!

View File

@ -1681,6 +1681,7 @@ bool QTime::setHMS(int h, int m, int s, int ms)
QTime QTime::addSecs(int s) const
{
s %= SECS_PER_DAY;
return addMSecs(s * 1000);
}

View File

@ -59,8 +59,13 @@ static qint64 absoluteToNSecs(qint64 cpuTime)
{
if (info.denom == 0)
mach_timebase_info(&info);
#ifdef __LP64__
__uint128_t nsecs = static_cast<__uint128_t>(cpuTime) * info.numer / info.denom;
return static_cast<qint64>(nsecs);
#else
qint64 nsecs = cpuTime * info.numer / info.denom;
return nsecs;
#endif
}
static qint64 absoluteToMSecs(qint64 cpuTime)

View File

@ -116,6 +116,10 @@ int qFindString(const QChar *haystack, int haystackLen, int from,
A good text on regexps is \e {Mastering Regular Expressions}
(Third Edition) by Jeffrey E. F. Friedl, ISBN 0-596-52812-4.
\note In Qt 5, the new QRegularExpression class provides a Perl
compatible implementation of regular expressions and is recommended
in place of QRegExp.
\tableofcontents
\section1 Introduction

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
** Copyright (C) 2015 Giuseppe D'Angelo <dangelog@gmail.com>.
** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
@ -1326,48 +1326,45 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
int * const captureOffsets = priv->capturedOffsets.data();
const int captureOffsetsCount = priv->capturedOffsets.size();
int realOffset = offset + subjectStart;
const int realSubjectLength = subjectLength + subjectStart;
const unsigned short * const subjectUtf16 = subject.utf16();
const unsigned short * const subjectUtf16 = subject.utf16() + subjectStart;
int result;
if (!previousMatchWasEmpty) {
result = pcre16SafeExec(compiledPattern, currentStudyData,
subjectUtf16, realSubjectLength,
realOffset, pcreOptions,
subjectUtf16, subjectLength,
offset, pcreOptions,
captureOffsets, captureOffsetsCount);
} else {
result = pcre16SafeExec(compiledPattern, currentStudyData,
subjectUtf16, realSubjectLength,
realOffset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED,
subjectUtf16, subjectLength,
offset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED,
captureOffsets, captureOffsetsCount);
if (result == PCRE_ERROR_NOMATCH) {
++realOffset;
++offset;
if (usingCrLfNewlines
&& realOffset < realSubjectLength
&& subjectUtf16[realOffset - 1] == QLatin1Char('\r')
&& subjectUtf16[realOffset] == QLatin1Char('\n')) {
++realOffset;
} else if (realOffset < realSubjectLength
&& QChar::isLowSurrogate(subjectUtf16[realOffset])) {
++realOffset;
&& offset < subjectLength
&& subjectUtf16[offset - 1] == QLatin1Char('\r')
&& subjectUtf16[offset] == QLatin1Char('\n')) {
++offset;
} else if (offset < subjectLength
&& QChar::isLowSurrogate(subjectUtf16[offset])) {
++offset;
}
result = pcre16SafeExec(compiledPattern, currentStudyData,
subjectUtf16, realSubjectLength,
realOffset, pcreOptions,
subjectUtf16, subjectLength,
offset, pcreOptions,
captureOffsets, captureOffsetsCount);
}
}
#ifdef QREGULAREXPRESSION_DEBUG
qDebug() << "Matching" << pattern << "against" << subject
<< "starting at" << subjectStart << "len" << subjectLength << "real len" << realSubjectLength
<< "offset" << offset << "real offset" << realOffset
<< "starting at" << subjectStart << "len" << subjectLength
<< "offset" << offset
<< matchType << matchOptions << previousMatchWasEmpty
<< "result" << result;
#endif
@ -2057,7 +2054,7 @@ QString QRegularExpressionMatch::captured(int nth) const
if (start == -1) // didn't capture
return QString();
return d->subject.mid(start, capturedLength(nth));
return d->subject.mid(start + d->subjectStart, capturedLength(nth));
}
/*!
@ -2078,7 +2075,7 @@ QStringRef QRegularExpressionMatch::capturedRef(int nth) const
if (start == -1) // didn't capture
return QStringRef();
return d->subject.midRef(start, capturedLength(nth));
return d->subject.midRef(start + d->subjectStart, capturedLength(nth));
}
/*!

View File

@ -212,6 +212,9 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
int blue_scale = 0;
int alpha_scale = 0;
if (!d->isSequential())
d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4 ? BMP_WIN : bi.biSize)); // goto start of colormap or masks
if (bi.biSize >= BMP_WIN4 || (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32))) {
if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
return false;
@ -299,9 +302,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
image.setDotsPerMeterX(bi.biXPelsPerMeter);
image.setDotsPerMeterY(bi.biYPelsPerMeter);
if (!d->isSequential())
d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap
if (ncols > 0) { // read color table
uchar rgb[4];
int rgb_len = t == BMP_OLD ? 3 : 4;

View File

@ -4237,9 +4237,6 @@ QImage QImage::alphaChannel() const
if (!d)
return QImage();
if (d->format == QImage::Format_Alpha8)
return *this;
int w = d->width;
int h = d->height;
@ -4269,6 +4266,10 @@ QImage QImage::alphaChannel() const
src_data += d->bytes_per_line;
dest_data += image.d->bytes_per_line;
}
} else if (d->format == Format_Alpha8) {
const uchar *src_data = d->data;
uchar *dest_data = image.d->data;
memcpy(dest_data, src_data, d->bytes_per_line * h);
} else {
QImage alpha32 = *this;
bool canSkipConversion = (d->format == Format_ARGB32 || d->format == Format_ARGB32_Premultiplied);

View File

@ -449,8 +449,7 @@ static QWindowGeometrySpecification windowGeometrySpecification;
\row
\li Miscellaneous
\li startingUp(),
closingDown(),
type().
closingDown().
\endtable
\sa QCoreApplication, QAbstractEventDispatcher, QEventLoop

View File

@ -386,9 +386,7 @@ QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e)
result = find(e);
if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) {
// Try to find a match without keypad modifier
QKeyEvent event = *e;
event.setModifiers(e->modifiers() & ~Qt::KeypadModifier);
result = find(&event);
result = find(e, Qt::KeypadModifier);
}
if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) {
// If Shift + Key_Backtab, also try Shift + Qt::Key_Tab
@ -441,13 +439,13 @@ bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const
which can be access through matches().
\sa matches
*/
QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e)
QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifiers)
{
Q_D(QShortcutMap);
if (!d->sequences.count())
return QKeySequence::NoMatch;
createNewSequences(e, d->newEntries);
createNewSequences(e, d->newEntries, ignoredModifiers);
#if defined(DEBUG_QSHORTCUTMAP)
qDebug() << "Possible shortcut key sequences:" << d->newEntries;
#endif
@ -549,7 +547,7 @@ void QShortcutMap::clearSequence(QVector<QKeySequence> &ksl)
Alters \a seq to the new sequence state, based on the
current sequence state, and the new key event \a e.
*/
void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl)
void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl, int ignoredModifiers)
{
Q_D(QShortcutMap);
QList<int> possibleKeys = QKeyMapper::possibleKeys(e);
@ -579,7 +577,7 @@ void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl)
curKsl.setKey(0, 2);
curKsl.setKey(0, 3);
}
curKsl.setKey(possibleKeys.at(pkNum), index);
curKsl.setKey(possibleKeys.at(pkNum) & ~ignoredModifiers, index);
}
}
}

View File

@ -88,10 +88,10 @@ private:
QKeySequence::SequenceMatch state();
void dispatchEvent(QKeyEvent *e);
QKeySequence::SequenceMatch find(QKeyEvent *e);
QKeySequence::SequenceMatch find(QKeyEvent *e, int ignoredModifiers = 0);
QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const;
QVector<const QShortcutEntry *> matches() const;
void createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl);
void createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl, int ignoredModifiers);
void clearSequence(QVector<QKeySequence> &ksl);
int translateModifiers(Qt::KeyboardModifiers modifiers);

View File

@ -525,7 +525,8 @@ bool QOpenGLShader::compileSourceCode(const char *source)
// The precision qualifiers are useful on OpenGL/ES systems,
// but usually not present on desktop systems.
const QSurfaceFormat currentSurfaceFormat = QOpenGLContext::currentContext()->format();
QOpenGLContext *ctx = QOpenGLContext::currentContext();
const QSurfaceFormat currentSurfaceFormat = ctx->format();
QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(QOpenGLContext::currentContext());
if (currentSurfaceFormat.renderableType() == QSurfaceFormat::OpenGL
|| ctx_d->workaround_missingPrecisionQualifiers
@ -545,10 +546,16 @@ bool QOpenGLShader::compileSourceCode(const char *source)
}
#endif
// Append #line directive in order to compensate for text insertion
QByteArray lineDirective = QStringLiteral("#line %1\n").arg(versionDirectivePosition.line).toUtf8();
sourceChunks.append(lineDirective.constData());
sourceChunkLengths.append(GLint(lineDirective.length()));
QByteArray lineDirective;
// #line is rejected by some drivers:
// "2.1 Mesa 8.1-devel (git-48a3d4e)" or "MESA 2.1 Mesa 8.1-devel"
const char *version = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_VERSION));
if (!version || !strstr(version, "2.1 Mesa 8")) {
// Append #line directive in order to compensate for text insertion
lineDirective = QStringLiteral("#line %1\n").arg(versionDirectivePosition.line).toUtf8();
sourceChunks.append(lineDirective.constData());
sourceChunkLengths.append(GLint(lineDirective.length()));
}
// Append rest of shader code
sourceChunks.append(source + versionDirectivePosition.position);

View File

@ -305,7 +305,10 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest,
for (int x = 0; x < dw; x++) {
const unsigned int *pix = sptr + xpoints[x];
const int xap = xapoints[x];
*dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap);
if (xap > 0)
*dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap);
else
*dptr = pix[0];
dptr++;
}
}

View File

@ -863,8 +863,8 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
const Q16Dot16 iLeft = int(left);
const Q16Dot16 iRight = int(right);
const Q16Dot16 leftWidth = IntToQ16Dot16(iLeft + 1)
- FloatToQ16Dot16(left);
const Q16Dot16 rightWidth = FloatToQ16Dot16(right)
- qSafeFloatToQ16Dot16(left);
const Q16Dot16 rightWidth = qSafeFloatToQ16Dot16(right)
- IntToQ16Dot16(iRight);
Q16Dot16 coverage[3];
@ -898,8 +898,8 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
const Q16Dot16 iTopFP = IntToQ16Dot16(int(pa.y()));
const Q16Dot16 iBottomFP = IntToQ16Dot16(int(pb.y()));
const Q16Dot16 yPa = FloatToQ16Dot16(pa.y());
const Q16Dot16 yPb = FloatToQ16Dot16(pb.y());
const Q16Dot16 yPa = qSafeFloatToQ16Dot16(pa.y());
const Q16Dot16 yPb = qSafeFloatToQ16Dot16(pb.y());
for (Q16Dot16 yFP = iTopFP; yFP <= iBottomFP; yFP += Q16Dot16Factor) {
const Q16Dot16 rowHeight = qMin(yFP + Q16Dot16Factor, yPb)
- qMax(yFP, yPa);
@ -983,16 +983,16 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
const Q16Dot16 iRightFP = IntToQ16Dot16(int(right.y()));
const Q16Dot16 iBottomFP = IntToQ16Dot16(int(bottomBound));
Q16Dot16 leftIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topLeftSlope);
Q16Dot16 rightIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topRightSlope);
Q16Dot16 leftIntersectAf = qSafeFloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topLeftSlope);
Q16Dot16 rightIntersectAf = qSafeFloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topRightSlope);
Q16Dot16 leftIntersectBf = 0;
Q16Dot16 rightIntersectBf = 0;
if (iLeftFP < iTopFP)
leftIntersectBf = FloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * bottomLeftSlope);
leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * bottomLeftSlope);
if (iRightFP < iTopFP)
rightIntersectBf = FloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * bottomRightSlope);
rightIntersectBf = qSafeFloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * bottomRightSlope);
Q16Dot16 rowTop, rowBottomLeft, rowBottomRight, rowTopLeft, rowTopRight, rowBottom;
Q16Dot16 topLeftIntersectAf, topLeftIntersectBf, topRightIntersectAf, topRightIntersectBf;
@ -1000,10 +1000,10 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
int leftMin, leftMax, rightMin, rightMax;
const Q16Dot16 yTopFP = FloatToQ16Dot16(top.y());
const Q16Dot16 yLeftFP = FloatToQ16Dot16(left.y());
const Q16Dot16 yRightFP = FloatToQ16Dot16(right.y());
const Q16Dot16 yBottomFP = FloatToQ16Dot16(bottom.y());
const Q16Dot16 yTopFP = qSafeFloatToQ16Dot16(top.y());
const Q16Dot16 yLeftFP = qSafeFloatToQ16Dot16(left.y());
const Q16Dot16 yRightFP = qSafeFloatToQ16Dot16(right.y());
const Q16Dot16 yBottomFP = qSafeFloatToQ16Dot16(bottom.y());
rowTop = qMax(iTopFP, yTopFP);
topLeftIntersectAf = leftIntersectAf +
@ -1021,7 +1021,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
if (yFP == iLeftFP) {
const int y = Q16Dot16ToInt(yFP);
leftIntersectBf = FloatToQ16Dot16(left.x() + (y - left.y()) * bottomLeftSlope);
leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + (y - left.y()) * bottomLeftSlope);
topLeftIntersectBf = leftIntersectBf + Q16Dot16Multiply(bottomLeftSlopeFP, rowTopLeft - yFP);
bottomLeftIntersectAf = leftIntersectAf + Q16Dot16Multiply(topLeftSlopeFP, rowBottomLeft - yFP);
} else {
@ -1031,7 +1031,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
if (yFP == iRightFP) {
const int y = Q16Dot16ToInt(yFP);
rightIntersectBf = FloatToQ16Dot16(right.x() + (y - right.y()) * bottomRightSlope);
rightIntersectBf = qSafeFloatToQ16Dot16(right.x() + (y - right.y()) * bottomRightSlope);
topRightIntersectBf = rightIntersectBf + Q16Dot16Multiply(bottomRightSlopeFP, rowTopRight - yFP);
bottomRightIntersectAf = rightIntersectAf + Q16Dot16Multiply(topRightSlopeFP, rowBottomRight - yFP);
} else {

View File

@ -74,6 +74,16 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr
}
}
template<typename T>
static inline bool qSafeFromBigEndian(const uchar *source, const uchar *end, T *output)
{
if (source + sizeof(T) > end)
return false;
*output = qFromBigEndian<T>(source);
return true;
}
// Harfbuzz helper functions
#ifdef QT_ENABLE_HARFBUZZ_NG
@ -1039,26 +1049,38 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
return;
const uchar *table = reinterpret_cast<const uchar *>(tab.constData());
const uchar *end = table + tab.size();
quint16 version;
if (!qSafeFromBigEndian(table, end, &version))
return;
unsigned short version = qFromBigEndian<quint16>(table);
if (version != 0) {
// qDebug("wrong version");
return;
}
unsigned short numTables = qFromBigEndian<quint16>(table + 2);
quint16 numTables;
if (!qSafeFromBigEndian(table + 2, end, &numTables))
return;
{
int offset = 4;
for(int i = 0; i < numTables; ++i) {
if (offset + 6 > tab.size()) {
// qDebug("offset out of bounds");
goto end;
}
const uchar *header = table + offset;
ushort version = qFromBigEndian<quint16>(header);
ushort length = qFromBigEndian<quint16>(header+2);
ushort coverage = qFromBigEndian<quint16>(header+4);
quint16 version;
if (!qSafeFromBigEndian(header, end, &version))
goto end;
quint16 length;
if (!qSafeFromBigEndian(header + 2, end, &length))
goto end;
quint16 coverage;
if (!qSafeFromBigEndian(header + 4, end, &coverage))
goto end;
// qDebug("subtable: version=%d, coverage=%x",version, coverage);
if(version == 0 && coverage == 0x0001) {
if (offset + length > tab.size()) {
@ -1067,7 +1089,10 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
}
const uchar *data = table + offset + 6;
ushort nPairs = qFromBigEndian<quint16>(data);
quint16 nPairs;
if (!qSafeFromBigEndian(data, end, &nPairs))
goto end;
if(nPairs * 6 + 8 > length - 6) {
// qDebug("corrupt table!");
// corrupt table
@ -1077,8 +1102,21 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
int off = 8;
for(int i = 0; i < nPairs; ++i) {
QFontEngine::KernPair p;
p.left_right = (((uint)qFromBigEndian<quint16>(data+off)) << 16) + qFromBigEndian<quint16>(data+off+2);
p.adjust = QFixed(((int)(short)qFromBigEndian<quint16>(data+off+4))) / scalingFactor;
quint16 tmp;
if (!qSafeFromBigEndian(data + off, end, &tmp))
goto end;
p.left_right = uint(tmp) << 16;
if (!qSafeFromBigEndian(data + off + 2, end, &tmp))
goto end;
p.left_right |= tmp;
if (!qSafeFromBigEndian(data + off + 4, end, &tmp))
goto end;
p.adjust = QFixed(int(short(tmp))) / scalingFactor;
kerning_pairs.append(p);
off += 6;
}
@ -1098,26 +1136,31 @@ int QFontEngine::glyphCount() const
QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p'));
if (maxpTable.size() < 6)
return 0;
return qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(maxpTable.constData() + 4));
const uchar *source = reinterpret_cast<const uchar *>(maxpTable.constData() + 4);
const uchar *end = source + maxpTable.size();
quint16 count = 0;
qSafeFromBigEndian(source, end, &count);
return count;
}
const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize)
{
const uchar *header = table;
if (tableSize < 4)
return 0;
const uchar *endPtr = table + tableSize;
// version check
if (qFromBigEndian<quint16>(header) != 0)
quint16 version;
if (!qSafeFromBigEndian(header, endPtr, &version) || version != 0)
return 0;
unsigned short numTables = qFromBigEndian<quint16>(header + 2);
const uchar *maps = table + 4;
if (maps + 8 * numTables > endPtr)
quint16 numTables;
if (!qSafeFromBigEndian(header + 2, endPtr, &numTables))
return 0;
const uchar *maps = table + 4;
enum {
Invalid,
AppleRoman,
@ -1132,8 +1175,14 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
int tableToUse = -1;
int score = Invalid;
for (int n = 0; n < numTables; ++n) {
const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n);
const quint16 platformSpecificId = qFromBigEndian<quint16>(maps + 8 * n + 2);
quint16 platformId;
if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId))
return 0;
quint16 platformSpecificId;
if (!qSafeFromBigEndian(maps + 8 * n + 2, endPtr, &platformSpecificId))
return 0;
switch (platformId) {
case 0: // Unicode
if (score < Unicode &&
@ -1187,20 +1236,30 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
resolveTable:
*isSymbolFont = (symbolTable > -1);
unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4);
quint32 unicode_table;
if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table))
return 0;
if (!unicode_table || unicode_table + 8 > tableSize)
if (!unicode_table)
return 0;
// get the header of the unicode table
header = table + unicode_table;
unsigned short format = qFromBigEndian<quint16>(header);
unsigned int length;
if(format < 8)
length = qFromBigEndian<quint16>(header + 2);
else
length = qFromBigEndian<quint32>(header + 4);
quint16 format;
if (!qSafeFromBigEndian(header, endPtr, &format))
return 0;
quint32 length;
if (format < 8) {
quint16 tmp;
if (!qSafeFromBigEndian(header + 2, endPtr, &tmp))
return 0;
length = tmp;
} else {
if (!qSafeFromBigEndian(header + 4, endPtr, &length))
return 0;
}
if (table + unicode_table + length > endPtr)
return 0;
@ -1215,7 +1274,7 @@ resolveTable:
// Check that none of the latin1 range are in the unicode table
bool unicodeTableHasLatin1 = false;
for (int uc=0x00; uc<0x100; ++uc) {
if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {
unicodeTableHasLatin1 = true;
break;
}
@ -1225,7 +1284,7 @@ resolveTable:
bool unicodeTableHasSymbols = false;
if (!unicodeTableHasLatin1) {
for (int uc=0xf000; uc<0xf100; ++uc) {
if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {
unicodeTableHasSymbols = true;
break;
}
@ -1243,12 +1302,17 @@ resolveTable:
return table + unicode_table;
}
quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode)
{
unsigned short format = qFromBigEndian<quint16>(cmap);
const uchar *end = cmap + cmapSize;
quint16 format;
if (!qSafeFromBigEndian(cmap, end, &format))
return 0;
if (format == 0) {
if (unicode < 256)
return (int) *(cmap+6+unicode);
const uchar *ptr = cmap + 6 + unicode;
if (unicode < 256 && ptr < end)
return quint32(*ptr);
} else if (format == 4) {
/* some fonts come with invalid cmap tables, where the last segment
specified end = start = rangeoffset = 0xffff, delta = 0x0001
@ -1257,25 +1321,49 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
*/
if(unicode >= 0xffff)
return 0;
quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6);
quint16 segCountX2;
if (!qSafeFromBigEndian(cmap + 6, end, &segCountX2))
return 0;
const unsigned char *ends = cmap + 14;
int i = 0;
for (; i < segCountX2/2 && qFromBigEndian<quint16>(ends + 2*i) < unicode; i++) {}
for (; i < segCountX2/2; ++i) {
quint16 codePoint;
if (!qSafeFromBigEndian(ends + 2 * i, end, &codePoint))
return 0;
if (codePoint >= unicode)
break;
}
const unsigned char *idx = ends + segCountX2 + 2 + 2*i;
quint16 startIndex = qFromBigEndian<quint16>(idx);
quint16 startIndex;
if (!qSafeFromBigEndian(idx, end, &startIndex))
return 0;
if (startIndex > unicode)
return 0;
idx += segCountX2;
qint16 idDelta = (qint16)qFromBigEndian<quint16>(idx);
quint16 tmp;
if (!qSafeFromBigEndian(idx, end, &tmp))
return 0;
qint16 idDelta = qint16(tmp);
idx += segCountX2;
quint16 idRangeoffset_t = (quint16)qFromBigEndian<quint16>(idx);
quint16 idRangeoffset_t;
if (!qSafeFromBigEndian(idx, end, &idRangeoffset_t))
return 0;
quint16 glyphIndex;
if (idRangeoffset_t) {
quint16 id = qFromBigEndian<quint16>(idRangeoffset_t + 2*(unicode - startIndex) + idx);
quint16 id;
if (!qSafeFromBigEndian(idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id))
return 0;
if (id)
glyphIndex = (idDelta + id) % 0x10000;
else
@ -1285,13 +1373,19 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
}
return glyphIndex;
} else if (format == 6) {
quint16 tableSize = qFromBigEndian<quint16>(cmap + 2);
quint16 tableSize;
if (!qSafeFromBigEndian(cmap + 2, end, &tableSize))
return 0;
quint16 firstCode6 = qFromBigEndian<quint16>(cmap + 6);
quint16 firstCode6;
if (!qSafeFromBigEndian(cmap + 6, end, &firstCode6))
return 0;
if (unicode < firstCode6)
return 0;
quint16 entryCount6 = qFromBigEndian<quint16>(cmap + 8);
quint16 entryCount6;
if (!qSafeFromBigEndian(cmap + 8, end, &entryCount6))
return 0;
if (entryCount6 * 2 + 10 > tableSize)
return 0;
@ -1300,9 +1394,14 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
return 0;
quint16 entryIndex6 = unicode - firstCode6;
return qFromBigEndian<quint16>(cmap + 10 + (entryIndex6 * 2));
quint16 index = 0;
qSafeFromBigEndian(cmap + 10 + (entryIndex6 * 2), end, &index);
return index;
} else if (format == 12) {
quint32 nGroups = qFromBigEndian<quint32>(cmap + 12);
quint32 nGroups;
if (!qSafeFromBigEndian(cmap + 12, end, &nGroups))
return 0;
cmap += 16; // move to start of groups
@ -1310,13 +1409,24 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
while (left <= right) {
int middle = left + ( ( right - left ) >> 1 );
quint32 startCharCode = qFromBigEndian<quint32>(cmap + 12*middle);
quint32 startCharCode;
if (!qSafeFromBigEndian(cmap + 12 * middle, end, &startCharCode))
return 0;
if(unicode < startCharCode)
right = middle - 1;
else {
quint32 endCharCode = qFromBigEndian<quint32>(cmap + 12*middle + 4);
if(unicode <= endCharCode)
return qFromBigEndian<quint32>(cmap + 12*middle + 8) + unicode - startCharCode;
quint32 endCharCode;
if (!qSafeFromBigEndian(cmap + 12 * middle + 4, end, &endCharCode))
return 0;
if (unicode <= endCharCode) {
quint32 index;
if (!qSafeFromBigEndian(cmap + 12 * middle + 8, end, &index))
return 0;
return index + unicode - startCharCode;
}
left = middle + 1;
}
}

View File

@ -240,7 +240,7 @@ public:
QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const;
static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize);
static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode);
static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode);
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);

View File

@ -322,9 +322,9 @@ bool QFontEngineQPF2::getSfntTableData(uint tag, uchar *buffer, uint *length) co
glyph_t QFontEngineQPF2::glyphIndex(uint ucs4) const
{
glyph_t glyph = getTrueTypeGlyphIndex(cmap, ucs4);
glyph_t glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
if (glyph == 0 && symbol && ucs4 < 0x100)
glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000);
glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000);
if (!findGlyph(glyph))
glyph = 0;
@ -348,16 +348,16 @@ bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyp
QStringIterator it(str, str + len);
while (it.hasNext()) {
const uint uc = it.next();
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
++glyph_pos;
}
} else {
QStringIterator it(str, str + len);
while (it.hasNext()) {
const uint uc = it.next();
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
#if 0 && defined(DEBUG_FONTENGINE)
QChar c(uc);
if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c))

View File

@ -1656,8 +1656,8 @@ namespace {
bool checkFullOtherwiseExtend(QScriptLine &line);
QFixed calculateNewWidth(const QScriptLine &line) const {
return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth
- qMin(rightBearing, QFixed());
return line.textWidth + tmpData.textWidth + spaceData.textWidth
+ softHyphenWidth + negativeRightBearing();
}
inline glyph_t currentGlyph() const
@ -1677,33 +1677,51 @@ namespace {
}
}
inline void adjustRightBearing(glyph_t glyph)
inline void calculateRightBearing(glyph_t glyph)
{
qreal rb;
fontEngine->getGlyphBearings(glyph, 0, &rb);
rightBearing = qMin(QFixed(), QFixed::fromReal(rb));
// We only care about negative right bearings, so we limit the range
// of the bearing here so that we can assume it's negative in the rest
// of the code, as well ase use QFixed(1) as a sentinel to represent
// the state where we have yet to compute the right bearing.
rightBearing = qMin(QFixed::fromReal(rb), QFixed(0));
}
inline void adjustRightBearing()
inline void calculateRightBearing()
{
if (currentPosition <= 0)
return;
adjustRightBearing(currentGlyph());
calculateRightBearing(currentGlyph());
}
inline void adjustPreviousRightBearing()
inline void calculateRightBearingForPreviousGlyph()
{
if (previousGlyph > 0)
adjustRightBearing(previousGlyph);
calculateRightBearing(previousGlyph);
}
static const QFixed RightBearingNotCalculated;
inline void resetRightBearing()
{
rightBearing = QFixed(1); // Any positive number is defined as invalid since only
// negative right bearings are interesting to us.
rightBearing = RightBearingNotCalculated;
}
// We express the negative right bearing as an absolute number
// so that it can be applied to the width using addition.
inline QFixed negativeRightBearing() const
{
if (rightBearing == RightBearingNotCalculated)
return QFixed(0);
return qAbs(rightBearing);
}
};
const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1);
inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
{
LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal());
@ -1856,7 +1874,7 @@ void QTextLine::layout_helper(int maxGlyphs)
current, lbh.logClusters, lbh.glyphs);
} else {
lbh.tmpData.length++;
lbh.adjustPreviousRightBearing();
lbh.calculateRightBearingForPreviousGlyph();
}
line += lbh.tmpData;
goto found;
@ -1938,22 +1956,29 @@ void QTextLine::layout_helper(int maxGlyphs)
lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
}
// The actual width of the text needs to take the right bearing into account. The
// right bearing is left-ward, which means that if the rightmost pixel is to the right
// of the advance of the glyph, the bearing will be negative. We flip the sign
// for the code to be more readable. Logic borrowed from qfontmetrics.cpp.
// We ignore the right bearing if the minimum negative bearing is too little to
// expand the text beyond the edge.
if (sb_or_ws|breakany) {
QFixed rightBearing = lbh.rightBearing; // store previous right bearing
// To compute the final width of the text we need to take negative right bearing
// into account (negative right bearing means the glyph has pixel data past the
// advance length). Note that the negative right bearing is an absolute number,
// so that we can apply it to the width using straight forward addition.
// Store previous right bearing (for the already accepted glyph) in case we
// end up breaking due to the current glyph being too wide.
QFixed previousRightBearing = lbh.rightBearing;
// We ignore the right bearing if the minimum negative bearing is too little to
// expand the text beyond the edge.
if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width)
lbh.adjustRightBearing();
lbh.calculateRightBearing();
if (lbh.checkFullOtherwiseExtend(line)) {
// we are too wide, fix right bearing
if (rightBearing <= 0)
lbh.rightBearing = rightBearing; // take from cache
// We are too wide to accept the next glyph with its bearing, so we restore the
// right bearing to that of the previous glyph (the one that was already accepted),
// so that the bearing can be be applied to the final width of the text below.
if (previousRightBearing != LineBreakHelper::RightBearingNotCalculated)
lbh.rightBearing = previousRightBearing;
else
lbh.adjustPreviousRightBearing();
lbh.calculateRightBearingForPreviousGlyph();
if (!breakany) {
line.textWidth += lbh.softHyphenWidth;
@ -1970,10 +1995,14 @@ void QTextLine::layout_helper(int maxGlyphs)
LB_DEBUG("reached end of line");
lbh.checkFullOtherwiseExtend(line);
found:
if (lbh.rightBearing > 0 && !lbh.whiteSpaceOrObject) // If right bearing has not yet been adjusted
lbh.adjustRightBearing();
line.textAdvance = line.textWidth;
line.textWidth -= qMin(QFixed(), lbh.rightBearing);
// If right bearing has not been calculated yet, do that now
if (lbh.rightBearing == LineBreakHelper::RightBearingNotCalculated && !lbh.whiteSpaceOrObject)
lbh.calculateRightBearing();
// Then apply any negative right bearing
line.textWidth += lbh.negativeRightBearing();
if (line.length == 0) {
LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f",

View File

@ -971,7 +971,6 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
for (int i = 0; i < channelCount; ++i) {
if (channels[i].resendCurrent && (channels[i].state != QHttpNetworkConnectionChannel::ClosingState)) {
channels[i].resendCurrent = false;
channels[i].state = QHttpNetworkConnectionChannel::IdleState;
// if this is not possible, error will be emitted and connection terminated
if (!channels[i].resetUploadData())

View File

@ -58,6 +58,11 @@ QT_BEGIN_NAMESPACE
// TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp
// Because in-flight when sending a request, the server might close our connection (because the persistent HTTP
// connection times out)
// We use 3 because we can get a _q_error 3 times depending on the timing:
static const int reconnectAttemptsDefault = 3;
QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel()
: socket(0)
, ssl(false)
@ -69,7 +74,7 @@ QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel()
, resendCurrent(false)
, lastStatus(0)
, pendingEncrypt(false)
, reconnectAttempts(2)
, reconnectAttempts(reconnectAttemptsDefault)
, authMethod(QAuthenticatorPrivate::None)
, proxyAuthMethod(QAuthenticatorPrivate::None)
, authenticationCredentialsSent(false)
@ -106,19 +111,18 @@ void QHttpNetworkConnectionChannel::init()
socket->setProxy(QNetworkProxy::NoProxy);
#endif
// We want all signals (except the interactive ones) be connected as QueuedConnection
// because else we're falling into cases where we recurse back into the socket code
// and mess up the state. Always going to the event loop (and expecting that when reading/writing)
// is safer.
// After some back and forth in all the last years, this is now a DirectConnection because otherwise
// the state inside the *Socket classes gets messed up, also in conjunction with the socket notifiers
// which behave slightly differently on Windows vs Linux
QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
this, SLOT(_q_bytesWritten(qint64)),
Qt::QueuedConnection);
Qt::DirectConnection);
QObject::connect(socket, SIGNAL(connected()),
this, SLOT(_q_connected()),
Qt::QueuedConnection);
Qt::DirectConnection);
QObject::connect(socket, SIGNAL(readyRead()),
this, SLOT(_q_readyRead()),
Qt::QueuedConnection);
Qt::DirectConnection);
// The disconnected() and error() signals may already come
// while calling connectToHost().
@ -129,10 +133,10 @@ void QHttpNetworkConnectionChannel::init()
qRegisterMetaType<QAbstractSocket::SocketError>();
QObject::connect(socket, SIGNAL(disconnected()),
this, SLOT(_q_disconnected()),
Qt::QueuedConnection);
Qt::DirectConnection);
QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(_q_error(QAbstractSocket::SocketError)),
Qt::QueuedConnection);
Qt::DirectConnection);
#ifndef QT_NO_NETWORKPROXY
@ -147,7 +151,7 @@ void QHttpNetworkConnectionChannel::init()
// won't be a sslSocket if encrypt is false
QObject::connect(sslSocket, SIGNAL(encrypted()),
this, SLOT(_q_encrypted()),
Qt::QueuedConnection);
Qt::DirectConnection);
QObject::connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(_q_sslErrors(QList<QSslError>)),
Qt::DirectConnection);
@ -156,7 +160,7 @@ void QHttpNetworkConnectionChannel::init()
Qt::DirectConnection);
QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
this, SLOT(_q_encryptedBytesWritten(qint64)),
Qt::QueuedConnection);
Qt::DirectConnection);
if (ignoreAllSslErrors)
sslSocket->ignoreSslErrors();
@ -400,7 +404,7 @@ void QHttpNetworkConnectionChannel::allDone()
// reset the reconnection attempts after we receive a complete reply.
// in case of failures, each channel will attempt two reconnects before emitting error.
reconnectAttempts = 2;
reconnectAttempts = reconnectAttemptsDefault;
// now the channel can be seen as free/idle again, all signal emissions for the reply have been done
if (state != QHttpNetworkConnectionChannel::ClosingState)
@ -668,6 +672,15 @@ void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest()
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
}
void QHttpNetworkConnectionChannel::resendCurrentRequest()
{
requeueCurrentlyPipelinedRequests();
if (reply)
resendCurrent = true;
if (qobject_cast<QHttpNetworkConnection*>(connection))
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
}
bool QHttpNetworkConnectionChannel::isSocketBusy() const
{
return (state & QHttpNetworkConnectionChannel::BusyState);
@ -711,8 +724,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
return;
}
// read the available data before closing
if (isSocketWaiting() || isSocketReading()) {
// read the available data before closing (also done in _q_error for other codepaths)
if ((isSocketWaiting() || isSocketReading()) && socket->bytesAvailable()) {
if (reply) {
state = QHttpNetworkConnectionChannel::ReadingState;
_q_receiveReply();
@ -724,7 +737,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
state = QHttpNetworkConnectionChannel::IdleState;
requeueCurrentlyPipelinedRequests();
close();
pendingEncrypt = false;
}
@ -806,11 +820,19 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
errorCode = QNetworkReply::ConnectionRefusedError;
break;
case QAbstractSocket::RemoteHostClosedError:
// try to reconnect/resend before sending an error.
// while "Reading" the _q_disconnected() will handle this.
if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) {
// This error for SSL comes twice in a row, first from SSL layer ("The TLS/SSL connection has been closed") then from TCP layer.
// Depending on timing it can also come three times in a row (first time when we try to write into a closing QSslSocket).
// The reconnectAttempts handling catches the cases where we can re-send the request.
if (!reply && state == QHttpNetworkConnectionChannel::IdleState) {
// Not actually an error, it is normal for Keep-Alive connections to close after some time if no request
// is sent on them. No need to error the other replies below. Just bail out here.
// The _q_disconnected will handle the possibly pipelined replies
return;
} else if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) {
// Try to reconnect/resend before sending an error.
// While "Reading" the _q_disconnected() will handle this.
if (reconnectAttempts-- > 0) {
closeAndResendCurrentRequest();
resendCurrentRequest();
return;
} else {
errorCode = QNetworkReply::RemoteHostClosedError;
@ -821,11 +843,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
if (!reply->d_func()->expectContent()) {
// No content expected, this is a valid way to have the connection closed by the server
// We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState
QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection);
return;
}
if (reply->contentLength() == -1 && !reply->d_func()->isChunked()) {
// There was no content-length header and it's not chunked encoding,
// so this is a valid way to have the connection closed by the server
// We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState
QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection);
return;
}
// ok, we got a disconnect even though we did not expect it
@ -835,24 +861,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
// we can ignore the readbuffersize as the data is already
// in memory and we will not receive more data on the socket.
reply->setReadBufferSize(0);
reply->setDownstreamLimited(false);
_q_receiveReply();
#ifndef QT_NO_SSL
if (ssl) {
// QT_NO_OPENSSL. The QSslSocket can still have encrypted bytes in the plainsocket.
// So we need to check this if the socket is a QSslSocket. When the socket is flushed
// it will force a decrypt of the encrypted data in the plainsocket.
QSslSocket *sslSocket = static_cast<QSslSocket*>(socket);
qint64 beforeFlush = sslSocket->encryptedBytesAvailable();
while (sslSocket->encryptedBytesAvailable()) {
sslSocket->flush();
_q_receiveReply();
qint64 afterFlush = sslSocket->encryptedBytesAvailable();
if (afterFlush == beforeFlush)
break;
beforeFlush = afterFlush;
}
if (!reply) {
// No more reply assigned after the previous call? Then it had been finished successfully.
requeueCurrentlyPipelinedRequests();
state = QHttpNetworkConnectionChannel::IdleState;
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
return;
}
#endif
}
errorCode = QNetworkReply::RemoteHostClosedError;
@ -863,7 +880,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
case QAbstractSocket::SocketTimeoutError:
// try to reconnect/resend before sending an error.
if (state == QHttpNetworkConnectionChannel::WritingState && (reconnectAttempts-- > 0)) {
closeAndResendCurrentRequest();
resendCurrentRequest();
return;
}
errorCode = QNetworkReply::TimeoutError;
@ -877,7 +894,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
case QAbstractSocket::ProxyConnectionClosedError:
// try to reconnect/resend before sending an error.
if (reconnectAttempts-- > 0) {
closeAndResendCurrentRequest();
resendCurrentRequest();
return;
}
errorCode = QNetworkReply::ProxyConnectionClosedError;
@ -885,7 +902,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
case QAbstractSocket::ProxyConnectionTimeoutError:
// try to reconnect/resend before sending an error.
if (reconnectAttempts-- > 0) {
closeAndResendCurrentRequest();
resendCurrentRequest();
return;
}
errorCode = QNetworkReply::ProxyTimeoutError;
@ -933,8 +950,18 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
// send the next request
QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection);
if (that) //signal emission triggered event loop
close();
if (that) {
//signal emission triggered event loop
if (!socket)
state = QHttpNetworkConnectionChannel::IdleState;
else if (socket->state() == QAbstractSocket::UnconnectedState)
state = QHttpNetworkConnectionChannel::IdleState;
else
state = QHttpNetworkConnectionChannel::ClosingState;
// pendingEncrypt must only be true in between connected and encrypted states
pendingEncrypt = false;
}
}
#ifndef QT_NO_NETWORKPROXY
@ -958,7 +985,8 @@ void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetwor
void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead()
{
sendRequest();
if (reply)
sendRequest();
}
#ifndef QT_NO_SSL

View File

@ -169,6 +169,7 @@ public:
void handleUnexpectedEOF();
void closeAndResendCurrentRequest();
void resendCurrentRequest();
bool isSocketBusy() const;
bool isSocketWriting() const;

View File

@ -208,7 +208,7 @@ QByteArray QHttpNetworkReply::readAny()
return QByteArray();
// we'll take the last buffer, so schedule another read from http
if (d->downstreamLimited && d->responseData.bufferCount() == 1)
if (d->downstreamLimited && d->responseData.bufferCount() == 1 && !isFinished())
d->connection->d_func()->readMoreLater(this);
return d->responseData.read();
}

View File

@ -237,7 +237,12 @@ void QHttpProtocolHandler::_q_readyRead()
}
if (m_channel->isSocketWaiting() || m_channel->isSocketReading()) {
m_channel->state = QHttpNetworkConnectionChannel::ReadingState;
if (m_socket->bytesAvailable()) {
// We might get a spurious call from readMoreLater()
// call of the QHttpNetworkConnection even while the socket is disconnecting.
// Therefore check if there is actually bytes available before changing the channel state.
m_channel->state = QHttpNetworkConnectionChannel::ReadingState;
}
if (m_reply)
_q_receiveReply();
}
@ -250,7 +255,6 @@ bool QHttpProtocolHandler::sendRequest()
if (!m_reply) {
// heh, how should that happen!
qWarning() << "QAbstractProtocolHandler::sendRequest() called without QHttpNetworkReply";
m_channel->state = QHttpNetworkConnectionChannel::IdleState;
return false;
}

View File

@ -466,15 +466,18 @@ QList<QBearerEngine *> QNetworkConfigurationManagerPrivate::engines() const
void QNetworkConfigurationManagerPrivate::startPolling()
{
QMutexLocker locker(&mutex);
if(!pollTimer) {
if (!pollTimer) {
pollTimer = new QTimer(this);
pollTimer->setInterval(10000);
bool ok;
int interval = qgetenv("QT_BEARER_POLL_TIMEOUT").toInt(&ok);
if (!ok)
interval = 10000;//default 10 seconds
pollTimer->setInterval(interval);
pollTimer->setSingleShot(true);
connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollEngines()));
}
if(pollTimer->isActive())
if (pollTimer->isActive())
return;
foreach (QBearerEngine *engine, sessionEngines) {
@ -483,6 +486,7 @@ void QNetworkConfigurationManagerPrivate::startPolling()
break;
}
}
performAsyncConfigurationUpdate();
}
void QNetworkConfigurationManagerPrivate::pollEngines()

View File

@ -774,6 +774,7 @@ bool QAbstractSocketPrivate::canReadNotification()
void QAbstractSocketPrivate::canCloseNotification()
{
Q_Q(QAbstractSocket);
// Note that this method is only called on Windows. Other platforms close in the canReadNotification()
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::canCloseNotification()");
@ -783,7 +784,11 @@ void QAbstractSocketPrivate::canCloseNotification()
if (isBuffered) {
// Try to read to the buffer, if the read fail we can close the socket.
newBytes = buffer.size();
if (!readFromSocket()) {
qint64 oldReadBufferMaxSize = readBufferMaxSize;
readBufferMaxSize = 0; // temporarily disable max read buffer, we want to empty the OS buffer
bool hadReadFromSocket = readFromSocket();
readBufferMaxSize = oldReadBufferMaxSize;
if (!hadReadFromSocket) {
q->disconnectFromHost();
return;
}

View File

@ -2408,6 +2408,14 @@ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error)
qCDebug(lcSsl) << "\tstate =" << q->state();
qCDebug(lcSsl) << "\terrorString =" << q->errorString();
#endif
// this moves encrypted bytes from plain socket into our buffer
if (plainSocket->bytesAvailable()) {
qint64 tmpReadBufferMaxSize = readBufferMaxSize;
readBufferMaxSize = 0; // reset temporarily so the plain sockets completely drained drained
transmit();
readBufferMaxSize = tmpReadBufferMaxSize;
}
q->setSocketError(plainSocket->error());
q->setErrorString(plainSocket->errorString());
emit q->error(error);

View File

@ -1513,6 +1513,13 @@ void QSslSocketBackendPrivate::disconnected()
{
if (plainSocket->bytesAvailable() <= 0)
destroySslContext();
else {
// Move all bytes into the plain buffer
qint64 tmpReadBufferMaxSize = readBufferMaxSize;
readBufferMaxSize = 0; // reset temporarily so the plain socket buffer is completely drained
transmit();
readBufferMaxSize = tmpReadBufferMaxSize;
}
//if there is still buffered data in the plain socket, don't destroy the ssl context yet.
//it will be destroyed when the socket is deleted.
}

View File

@ -241,7 +241,8 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon
void QEGLPlatformContext::initialize()
{
updateFormatFromGL();
if (m_eglContext != EGL_NO_CONTEXT)
updateFormatFromGL();
}
// Base implementation for pbuffers. Subclasses will handle the specialized cases for

View File

@ -44,6 +44,8 @@ QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
QCocoaBackingStore::~QCocoaBackingStore()
{
if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle()))
[cocoaWindow->m_qtView clearBackingStore:this];
}
QPaintDevice *QCocoaBackingStore::paintDevice()

View File

@ -51,8 +51,7 @@ QT_END_NAMESPACE
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
@interface QT_MANGLE_NAMESPACE(QNSView) : NSView <NSTextInputClient> {
QImage m_backingStore;
qreal m_pixelRatio;
QCocoaBackingStore* m_backingStore;
QPoint m_backingStoreOffset;
CGImageRef m_maskImage;
uchar *m_maskData;
@ -86,6 +85,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
#endif
- (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset;
- (void)clearBackingStore:(QCocoaBackingStore *)backingStore;
- (void)setMaskRegion:(const QRegion *)region;
- (void)invalidateWindowShadowIfNeeded;
- (void)drawRect:(NSRect)dirtyRect;

View File

@ -134,7 +134,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
{
self = [super initWithFrame : NSMakeRect(0,0, 300,300)];
if (self) {
m_pixelRatio = 1.;
m_backingStore = 0;
m_maskImage = 0;
m_shouldInvalidateWindowShadow = false;
m_window = 0;
@ -376,7 +376,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
if (!m_platformWindow->m_inSetGeometry)
QWindowSystemInterface::flushWindowSystemEvents();
else
m_backingStore = QImage();
m_backingStore = 0;
}
}
@ -481,12 +481,16 @@ QT_WARNING_POP
- (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset
{
m_backingStore = backingStore->toImage();
m_pixelRatio = backingStore->getBackingStoreDevicePixelRatio();
m_backingStoreOffset = offset * m_pixelRatio;
foreach (QRect rect, region.rects()) {
m_backingStore = backingStore;
m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio();
foreach (QRect rect, region.rects())
[self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
}
}
- (void)clearBackingStore:(QCocoaBackingStore *)backingStore
{
if (backingStore == m_backingStore)
m_backingStore = 0;
}
- (BOOL) hasMask
@ -549,7 +553,7 @@ QT_WARNING_POP
if (m_platformWindow->m_drawContentBorderGradient)
NSDrawWindowBackground(dirtyRect);
if (m_backingStore.isNull())
if (!m_backingStore)
return;
// Calculate source and target rects. The target rect is the dirtyRect:
@ -557,10 +561,11 @@ QT_WARNING_POP
// The backing store source rect will be larger on retina displays.
// Scale dirtyRect by the device pixel ratio:
CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * m_pixelRatio,
dirtyRect.origin.y * m_pixelRatio,
dirtyRect.size.width * m_pixelRatio,
dirtyRect.size.height * m_pixelRatio);
const qreal devicePixelRatio = m_backingStore->getBackingStoreDevicePixelRatio();
CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio,
dirtyRect.origin.y * devicePixelRatio,
dirtyRect.size.width * devicePixelRatio,
dirtyRect.size.height * devicePixelRatio);
NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext];
CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort];
@ -586,7 +591,7 @@ QT_WARNING_POP
dirtyBackingRect.size.width,
dirtyBackingRect.size.height
);
CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore);
CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore->toImage());
CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect);
// Optimization: Copy frame buffer content instead of blending for

View File

@ -344,6 +344,46 @@
// -------------------------------------------------------------------------
- (void)sendKeyPressRelease:(Qt::Key)key modifiers:(Qt::KeyboardModifiers)modifiers
{
QKeyEvent press(QEvent::KeyPress, key, modifiers);
QKeyEvent release(QEvent::KeyRelease, key, modifiers);
[self sendEventToFocusObject:press];
[self sendEventToFocusObject:release];
}
- (void)cut:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_X modifiers:Qt::ControlModifier];
}
- (void)copy:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_C modifiers:Qt::ControlModifier];
}
- (void)paste:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_V modifiers:Qt::ControlModifier];
}
- (void)selectAll:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_A modifiers:Qt::ControlModifier];
}
- (void)delete:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_Delete modifiers:Qt::ControlModifier];
}
// -------------------------------------------------------------------------
- (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties
{
// As documented, we should not report textWillChange/textDidChange unless the text
@ -560,7 +600,7 @@
if (cursorPos != int(r.location + r.length) || cursorPos != anchorPos) {
attrs = QList<QInputMethodEvent::Attribute>();
attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, cursorPos, (cursorPos - anchorPos), 0);
attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, qMin(cursorPos, anchorPos), qAbs(cursorPos - anchorPos), 0);
e = QInputMethodEvent(m_markedText, attrs);
[self sendEventToFocusObject:e];
}
@ -678,10 +718,7 @@
return;
if ([text isEqualToString:@"\n"]) {
QKeyEvent press(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
QKeyEvent release(QEvent::KeyRelease, Qt::Key_Return, Qt::NoModifier);
[self sendEventToFocusObject:press];
[self sendEventToFocusObject:release];
[self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier];
if (self.returnKeyType == UIReturnKeyDone || self.returnKeyType == UIReturnKeyGo
|| self.returnKeyType == UIReturnKeySend || self.returnKeyType == UIReturnKeySearch)
@ -700,10 +737,7 @@
// Since we're posting im events directly to the focus object, we should do the
// same for key events. Otherwise they might end up in a different place or out
// of sync with im events.
QKeyEvent press(QEvent::KeyPress, (int)Qt::Key_Backspace, Qt::NoModifier);
QKeyEvent release(QEvent::KeyRelease, (int)Qt::Key_Backspace, Qt::NoModifier);
[self sendEventToFocusObject:press];
[self sendEventToFocusObject:release];
[self sendKeyPressRelease:Qt::Key_Backspace modifiers:Qt::NoModifier];
}
@end

View File

@ -190,8 +190,9 @@
- (void)setBounds:(CGRect)newBounds
{
Q_UNUSED(newBounds);
CGRect transformedWindowBounds = [self convertRect:self.window.bounds fromView:self.window];
[super setBounds:CGRectMake(0, 0, CGRectGetWidth(newBounds), CGRectGetHeight(transformedWindowBounds))];
[super setBounds:CGRectMake(0, 0, CGRectGetWidth(transformedWindowBounds), CGRectGetHeight(transformedWindowBounds))];
}
- (void)setCenter:(CGPoint)newCenter

View File

@ -181,9 +181,8 @@ void QWindowsFontEngine::getCMap()
bool symb = false;
if (ttf) {
cmapTable = getSfntTable(qbswap<quint32>(MAKE_TAG('c', 'm', 'a', 'p')));
int size = 0;
cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()),
cmapTable.size(), &symb, &size);
cmapTable.size(), &symb, &cmapSize);
}
if (!cmap) {
ttf = false;
@ -218,16 +217,16 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa
QStringIterator it(str, str + numChars);
while (it.hasNext()) {
const uint uc = it.next();
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
++glyph_pos;
}
} else if (ttf) {
QStringIterator it(str, str + numChars);
while (it.hasNext()) {
const uint uc = it.next();
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
++glyph_pos;
}
} else {
@ -275,6 +274,7 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
hasOutline(0),
lw(0),
cmap(0),
cmapSize(0),
lbearing(SHRT_MIN),
rbearing(SHRT_MIN),
x_height(-1),
@ -346,11 +346,11 @@ glyph_t QWindowsFontEngine::glyphIndex(uint ucs4) const
#if !defined(Q_OS_WINCE)
if (symbol) {
glyph = getTrueTypeGlyphIndex(cmap, ucs4);
glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
if (glyph == 0 && ucs4 < 0x100)
glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000);
glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000);
} else if (ttf) {
glyph = getTrueTypeGlyphIndex(cmap, ucs4);
glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
#else
if (tm.tmFirstChar > 60000) {
glyph = ucs4;

View File

@ -146,6 +146,7 @@ private:
TEXTMETRIC tm;
int lw;
const unsigned char *cmap;
int cmapSize;
QByteArray cmapTable;
mutable qreal lbearing;
mutable qreal rbearing;

View File

@ -199,18 +199,27 @@ void QWindowsInputContext::reset()
doneContext();
}
void QWindowsInputContext::setFocusObject(QObject *object)
void QWindowsInputContext::setFocusObject(QObject *)
{
// ### fixme: On Windows 8.1, it has been observed that the Input context
// remains active when this happens resulting in a lock-up. Consecutive
// key events still have VK_PROCESSKEY set and are thus ignored.
if (m_compositionContext.isComposing)
imeNotifyCancelComposition(m_compositionContext.hwnd);
reset();
updateEnabled();
}
void QWindowsInputContext::updateEnabled()
{
if (!QGuiApplication::focusObject())
return;
const QWindow *window = QGuiApplication::focusWindow();
if (object && window && window->handle()) {
if (window && window->handle()) {
QWindowsWindow *platformWindow = QWindowsWindow::baseWindowOf(window);
if (inputMethodAccepted()) {
const bool accepted = inputMethodAccepted();
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaInputMethods) << __FUNCTION__ << window << "accepted=" << accepted;
if (accepted) {
// Re-enable IME by associating default context saved on first disabling.
if (platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) {
ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext);
@ -234,6 +243,8 @@ void QWindowsInputContext::setFocusObject(QObject *object)
void QWindowsInputContext::update(Qt::InputMethodQueries queries)
{
if (queries & Qt::ImEnabled)
updateEnabled();
QPlatformInputContext::update(queries);
}

View File

@ -87,6 +87,7 @@ private:
void doneContext();
void startContextComposition();
void endContextComposition();
void updateEnabled();
const DWORD m_WM_MSIME_MOUSE;
static HIMC m_defaultContext;

View File

@ -990,12 +990,11 @@ QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, co
{
QVector<FORMATETC> formatetcs;
if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) {
//add DIBV5 if image has alpha channel
//add DIBV5 if image has alpha channel. Do not add CF_PNG here as it will confuse MS Office (QTBUG47656).
QImage image = qvariant_cast<QImage>(mimeData->imageData());
if (!image.isNull() && image.hasAlphaChannel())
formatetcs += setCf(CF_DIBV5);
formatetcs += setCf(CF_DIB);
formatetcs += setCf(CF_PNG); // QTBUG-86848, Paste into GIMP queries for PNG.
}
return formatetcs;
}
@ -1024,11 +1023,7 @@ bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMi
const QImage image = qvariant_cast<QImage>(mimeData->imageData());
if (image.isNull())
return false;
// QTBUG-11463, deny CF_DIB support for images with alpha to prevent loss of
// transparency in conversion.
return cf == CF_DIBV5
|| (cf == CF_DIB && !image.hasAlphaChannel())
|| cf == int(CF_PNG);
return cf == CF_DIBV5 || (cf == CF_DIB) || cf == int(CF_PNG);
}
bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const

View File

@ -1045,8 +1045,8 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled)
RegisterDragDrop(m_data.hwnd, m_dropTarget);
CoLockObjectExternal(m_dropTarget, true, true);
} else {
m_dropTarget->Release();
CoLockObjectExternal(m_dropTarget, false, true);
m_dropTarget->Release();
RevokeDragDrop(m_data.hwnd);
m_dropTarget = 0;
}

View File

@ -967,15 +967,6 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q
xXIGenericDeviceEvent *xiEvent = static_cast<xXIGenericDeviceEvent *>(event);
xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(xiEvent);
#ifdef XCB_USE_XINPUT22
// Synthesize mouse events since otherwise there are no mouse events from
// the pen on the XI 2.2+ path.
if (xi2MouseEvents() && eventListener)
eventListener->handleXIMouseEvent(reinterpret_cast<xcb_ge_event_t *>(event));
#else
Q_UNUSED(eventListener);
#endif
switch (xiEvent->evtype) {
case XI_ButtonPress: {
Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail);
@ -1058,6 +1049,16 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q
handled = false;
break;
}
#ifdef XCB_USE_XINPUT22
// Synthesize mouse events since otherwise there are no mouse events from
// the pen on the XI 2.2+ path.
if (xi2MouseEvents() && eventListener)
eventListener->handleXIMouseEvent(reinterpret_cast<xcb_ge_event_t *>(event));
#else
Q_UNUSED(eventListener);
#endif
return handled;
}

View File

@ -2208,17 +2208,17 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event)
switch (ev->evtype) {
case XI_ButtonPress:
qCDebug(lcQpaXInput, "XI2 mouse press, button %d", button);
qCDebug(lcQpaXInput, "XI2 mouse press, button %d, time %d", button, ev->time);
conn->setButton(button, true);
handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time);
break;
case XI_ButtonRelease:
qCDebug(lcQpaXInput, "XI2 mouse release, button %d", button);
qCDebug(lcQpaXInput, "XI2 mouse release, button %d, time %d", button, ev->time);
conn->setButton(button, false);
handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time);
break;
case XI_Motion:
qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d", event_x, event_y);
qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d, time %d", event_x, event_y, ev->time);
handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time);
break;
default:

View File

@ -803,7 +803,7 @@ void QUnixPrintWidgetPrivate::applyPrinterProperties()
QString cur = QDir::currentPath();
if (home.at(home.length()-1) != QLatin1Char('/'))
home += QLatin1Char('/');
if (cur.at(cur.length()-1) != QLatin1Char('/'))
if (!cur.isEmpty() && cur.at(cur.length()-1) != QLatin1Char('/'))
cur += QLatin1Char('/');
if (cur.left(home.length()) != home)
cur = home;

View File

@ -1332,6 +1332,9 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
if (r.isEmpty())
r = QSqlDriver::formatValue(field, trimStrings);
break;
case QVariant::Uuid:
r = QLatin1Char('\'') + field.value().toString() + QLatin1Char('\'');
break;
default:
r = QSqlDriver::formatValue(field, trimStrings);
break;

View File

@ -1425,10 +1425,13 @@ QGraphicsItem::~QGraphicsItem()
QObjectPrivate *p = QObjectPrivate::get(o);
p->wasDeleted = true;
if (p->declarativeData) {
if (QAbstractDeclarativeData::destroyed)
QAbstractDeclarativeData::destroyed(p->declarativeData, o);
if (QAbstractDeclarativeData::destroyed_qml1)
QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o);
if (static_cast<QAbstractDeclarativeDataImpl*>(p->declarativeData)->ownedByQml1) {
if (QAbstractDeclarativeData::destroyed_qml1)
QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o);
} else {
if (QAbstractDeclarativeData::destroyed)
QAbstractDeclarativeData::destroyed(p->declarativeData, o);
}
p->declarativeData = 0;
}
}

View File

@ -433,6 +433,9 @@ void QTreeView::setRootIsDecorated(bool show)
The height is obtained from the first item in the view. It is updated
when the data changes on that item.
\note If the editor size hint is bigger than the cell size hint, then the
size hint of the editor will be used.
By default, this property is \c false.
*/
bool QTreeView::uniformRowHeights() const

View File

@ -339,8 +339,7 @@ void QApplicationPrivate::createEventDispatcher()
\li Miscellaneous
\li closeAllWindows(),
startingUp(),
closingDown(),
type().
closingDown().
\endtable
\sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings

View File

@ -92,7 +92,7 @@ inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
be expressed using hasHeightForWidth(), heightForWidth(), and
minimumHeightForWidth(). For more explanation see the \e{Qt
Quarterly} article
\l{http://doc.qt.digia.com/qq/qq04-height-for-width.html}{Trading
\l{http://doc.qt.io/archives/qq/qq04-height-for-width.html}{Trading
Height for Width}.
\sa QLayout

View File

@ -1634,10 +1634,13 @@ QWidget::~QWidget()
}
if (d->declarativeData) {
if (QAbstractDeclarativeData::destroyed)
QAbstractDeclarativeData::destroyed(d->declarativeData, this);
if (QAbstractDeclarativeData::destroyed_qml1)
QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
if (QAbstractDeclarativeData::destroyed_qml1)
QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
} else {
if (QAbstractDeclarativeData::destroyed)
QAbstractDeclarativeData::destroyed(d->declarativeData, this);
}
d->declarativeData = 0; // don't activate again in ~QObject
}

View File

@ -445,11 +445,11 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
receiver = popupChild;
if (receiver != popup)
widgetPos = receiver->mapFromGlobal(event->globalPos());
QWidget *alien = m_widget->childAt(m_widget->mapFromGlobal(event->globalPos()));
QWidget *alien = receiver->childAt(receiver->mapFromGlobal(event->globalPos()));
QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(),
event->button(), event->buttons(), event->modifiers(), event->source());
e.setTimestamp(event->timestamp());
QApplicationPrivate::sendMouseEvent(receiver, &e, alien, m_widget, &qt_button_down, qt_last_mouse_receiver);
QApplicationPrivate::sendMouseEvent(receiver, &e, alien, receiver->window(), &qt_button_down, qt_last_mouse_receiver);
qt_last_mouse_receiver = receiver;
} else {
// close disabled popups when a mouse button is pressed or released

View File

@ -4682,7 +4682,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
tdi.value = pb->progress;
tdi.attributes = vertical ? 0 : kThemeTrackHorizontal;
if (isIndeterminate || tdi.value < tdi.max) {
const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9;
if (isIndeterminate || (tdi.value < tdi.max && !usingYosemiteOrLater)) {
if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject)))
tdi.trackInfo.progress.phase = animation->animationStep();
else if (opt->styleObject)

View File

@ -541,17 +541,21 @@ QRect QStyle::itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pi
QRect result;
int x, y, w, h;
rect.getRect(&x, &y, &w, &h);
const int pixmapWidth = pixmap.width()/pixmap.devicePixelRatio();
const int pixmapHeight = pixmap.height()/pixmap.devicePixelRatio();
if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter)
y += h/2 - pixmap.height()/2;
y += h/2 - pixmapHeight/2;
else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom)
y += h - pixmap.height();
y += h - pixmapHeight;
if ((alignment & Qt::AlignRight) == Qt::AlignRight)
x += w - pixmap.width();
x += w - pixmapWidth;
else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter)
x += w/2 - pixmap.width()/2;
x += w/2 - pixmapWidth/2;
else if ((alignment & Qt::AlignLeft) != Qt::AlignLeft && QApplication::isRightToLeft())
x += w - pixmap.width();
result = QRect(x, y, pixmap.width(), pixmap.height());
x += w - pixmapWidth;
result = QRect(x, y, pixmapWidth, pixmapHeight);
return result;
}
@ -2263,8 +2267,9 @@ int QStyle::sliderValueFromPosition(int min, int max, int pos, int span, bool up
standard palette is not used. In particular, the Windows XP,
Vista, and Mac styles do not use the standard palette, but make
use of native theme engines. With these styles, you should not set
the palette with QApplication::setStandardPalette().
the palette with QApplication::setPalette().
\sa QApplication::setPalette()
*/
QPalette QStyle::standardPalette() const
{

Some files were not shown because too many files have changed in this diff Show More